頑張っているが日本でイマイチ広まらないゲームエンジンについてメモ

あとで「なんだっけアレ」とならないように(忘れるわけがないものもあるが)
記録しておく。
実は自分が知らないだけで日本のゲームデベロッパーの大半のシェアを獲得していてもツッコミはナシでお願いしたい。

Amazon Lumberyard (無料 3D ゲームエンジンと開発環境)| AWS
CryEngineをベースに、Amazonが開発しているゲームエンジン
FlowCanvasから、Script Canvasへと移行。

CRYENGINE | The complete solution for next generation game development by Crytek
こちらもFlowCanvasからSchematycへと移行しようとしているところ。
日本で趣味で触っているという方はMMD界隈の人が多いような?

luxe engine | A lovingly hand crafted game engine
注目しているが、まだごく初期段階。
とりあえずワクワクできるのでアクセスしてみてほしい。

Godot Engine - Free and open source 2D and 3D game engine
GDScriptのほか、VisualScriptingもサポート。
色々頑張っているものの、コンソール機の公式サポートが無いので
インディーから一発当てたい人たちやつぶしがきくノウハウを求める人たちに普及しない原因になっているのではないだろうか(個人的な感想です。)

ShiVa Engine – ShiVa 2.0: The world's most cross-platform game engine just got even better. 1.9系はluaまわりがイマイチだった記憶。
2.0ではどうなのか?

Zero Engine - Make Everything DigiPenが開発中のゲームエンジン。 現状はPC専用?

xenko.com シリコンスタジオが開発しているゲームエンジン

PlayCanvas WebGL Game Engine
HTML5用3Dエンジン。
Unity3Dの経験のある人は短期間で使いこなすことが可能(だと思う)
バージョン管理など、色々本格的な開発に欲しい機能が欠けている
サクっと作って動かせるので、実はGameJamと相性がよいのでは?と思ったり...

Superpowers — Free 2D+3D game maker, open source
たしか、ローカルサーバーを動かしてそこ経由で編集する仕組みだったはず。
テキストエディタがもっと使いやすければ...あとデフォルトのバージョニング機能は微妙。

Armory | 3D Game Engine for Blender
ここに載せた時点ではまったく調べてない。
Blenderのライセンスには感染しない模様?

TextureAtlasからssce(SpriteStudioのセルマップ)を作るツール

海外ストアで買った画像素材をSpriteStudio5に組み込むのが怠かったので、
TextureAtlasのjsonからssceを作るツール作った
https://github.com/eims/genssce/

TexturePacker不要(元アトラスの生成自体はShoeboxFree SpritePackerなどでできるので)。
Photoshop不要。
逆に現状はNode環境が必要です。
あとでnexeか何かでネイティブexe対応したい。
↑しました。nexe版はnodeインストール不要なはず。
今更5かよと言われるかもしれませんが....

追記.
macでしか確認してないので、あとでwinでも確認します... 追記2. win10で動いた generator要素の中身は変えたほうがいいのだろうか?

MoonSharpでUnity側の処理の終了を待つ

MoonSharpでメッセージ流して待機するのにしばらく悩んだのでメモ。
DynValue.NewYieldReqを使った方法はうまくいかなかった。
何かうまい回避策があるのかもしれないが、現状はこれで良いことにしておく。
一応軽く動作チェックはしてあるけど、こんな時間に書いてるんでまだなんか落とし穴があったらごめんなさい

1秒毎にメッセージを流すサンプル

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using UniRx.Async;
using MoonSharp.Interpreter;

public class ScriptTest : MonoBehaviour
{
    private Script script;

    public void Start(){
        InitLua();
        this.script.DoString(@"
function wrapUnityCoroutine(co)
    for i in co do
        coroutine.yield(0)
    end
end

function message(...)
    wrapUnityCoroutine(playMessage(...))
end

function enterPub()
    message([[
よう、ずぶ濡れじゃねえか
今日はどこの狩場にいたんだ?
]],
[[
このスープはサービスだ
]]
)
end");
        var coroutine = script.CreateCoroutine(script.Globals["enterPub"]);
        StartCoroutine(RunLuaCoroutine(coroutine));
    }

    private void InitLua()
    {
        this.script = new Script();
        this.script.Globals["playMessage"] = new CallbackFunction((Func<ScriptExecutionContext, CallbackArguments, DynValue>)PlayMessage);
    }

    private DynValue PlayMessage(ScriptExecutionContext executionContext, CallbackArguments args)
    {
        var arr = args.GetArray();
        var en = PlayMessage(arr);
        // internalなのでMoonSharp側の修正が必要。
        return MoonSharp.Interpreter.Interop.Converters.ClrToScriptConversions.EnumerationToDynValue(script, en);
    }


    private IEnumerable PlayMessage(DynValue[] args)
    {
        for (var i = 0; i < args.Length; i++)
        {
            var val = args[i];
            var wait = true;
            var subject = PlayMessage(val.String);
            subject.Subscribe(_ =>
            {
                wait = false;
            });
            // yield return nullにするとEnumerableWrapperによって即座に次が呼ばれてしまうため、
            // メッセージ流してる間busy loopのような状態になる。
            // とりあえず0を返しておく。
            while (wait){
                yield return 0;
            }
        }
    }

    // メッセージ垂れ流して終わったら通知するやつのつもりで。
    private IObservable<Unit> PlayMessage(string str)
    {
        var subject = new Subject<Unit>();
        Observable.Timer(TimeSpan.FromSeconds(1)).Subscribe(_ =>
        {
            Debug.Log(str);
            subject.OnNext(Unit.Default);
        }).AddTo(this);
        return subject;
    }

    private IEnumerator RunLuaCoroutine(DynValue func)
    {
        var coroutine = func.Coroutine;
        while (true)
        {
            if (coroutine.State == CoroutineState.Dead){
                break;
            }
            yield return coroutine.Resume();
        }
    }
}

skookumscriptを書いてみよう

公式サイトのサンプルコードを読むための足がかりとして
Pawnに関数や変数を追加してみる簡単な流れを書いておきます...
言語のざっくり紹介は前回記事参照。

  • まず、プロジェクトでSkookumScript Pluginを有効にします。

  • SkookumScript IDEを起動してください。 f:id:eims:20180315222316p:plain:w400

  • Pawnを検索、test_funcを追加します。 f:id:eims:20180315222425p:plain:w400

  • 下記を参考に自由にコードを書いてみてください。
    IDE側で直接名前を付ける関数については、ファイル名=関数名となります。
    コメントは//です。
    また、記事の都合上日本語でコメントを書いていますが、日本語コメントは書けないようです。

// blueprint側から見えるようにする
&blueprint
(Integer v) String// 整数を受け取って文字列を返す
[
  !test : 100 // testを宣言、初期値100をbind
  test := test + v // testとvを足してtestに代入
  if test < 200
  [
    test.String + "is small"
  ]
  else
  [
    test.String + "is big"
  ]
]
  • コンパイルします。
    f:id:eims:20180315230851p:plain:w400

  • Pawnからtest_funcが呼べるようになりました。 f:id:eims:20180315230928p:plain:w400

簡単なコードしか書いてみていなかったので、今回初めて日本語NGということに気付きました。
メッセージなどはスクリプト側に書けませんね。

SkookumScriptを触ってみた

Stingrayが終わっちゃったからUE4の記事を書く

UE4と連携できるスクリプト言語、skookumscriptについてざっくり書いてみた。 割と良さげなのに日本語でskookumscriptについて言及している記事がほとんど見当たらない。 skookumscript.com

特徴(間違ってたらごめんぬ)

  • 組み込みクラスを含む各UClassに仮想関数やフィールドを生やすことができる。
    これがかなり嬉しい...
  • BP用関数は戻り値をBPクラスにすることはできない(おそらく循環参照で依存関係おかしくなるから)。C++クラスにすることはできる。 自分で用意したBPクラスにキャストするだけの関数は需要あると思うけどできない。 BP側でキャスト書きたくない人は基底クラス側に仮想関数生やしまくることになるかも?
  • execution pinなしのノードを作れない(たぶん)
  • skookum側のフィールドにBPからの直接アクセスはできず(たぶん)getter/setterが必要。 逆は不要。
  • 1クラス1ディレクトリ1関数1ファイル(ギョッとするが、意外にもIDEとの相性が良い)
  • 静的型付け。グルーコード部分は自動で更新される。
    スクリプト側、ゲーム本体側のインターフェース変更があったときの対応漏れが最小限に抑えられるので、地味に助かる.... 更新タイミングはBPコンパイル時だったかSKコンパイル時だったかよく観察していないです。すみません。

IDEについて

  • IDEは複数インスタンス起動できないみたい。
    デモプロジェクトと見比べながらの作業はしんどいかも。
  • 現状IDEWin64版しか提供されていません。
    実行は他プラットフォームでも可能。

Stingray 1.8リリース

前回はまったところで萎えて放置してました。すみません。

http://help.autodesk.com/view/Stingray/ENU/?guid=__stingray_help_release_notes_readme_1_8_html

困ってるところは解決してなさそうorz 気になったところ。

  • WebAssembly対応
  • スプラッシュスクリーンの追加が可能になったらしい。
  • HoloLensで動かない不具合が修正されたらしい(誰か動かしてみて)
  • plugin開発の情報が公開(これ今回のリリースと関係あったっけ?)。C++とJSを組み合わせるようだ。 github.com NativeCode不要ならJSだけで組めそうなようにみえる??

もうしばらく他の勉強して様子見かな… 日本語版リリースノート来たら更新するかも。

Luaコンポーネントから他のコンポーネントを参照したい

仕事のほうが忙しく、久々の記事なのですが…
うまくいっておらず、途中経過のみ掲載。

Luaで作ったEntityComponentから、他のComponentを参照するため
以下のようなコードを書いたんだけれど、numがずっと0
(Test2Behaviourを付けたEntityは配置済み)

local query_cache = {}
-- Called once each frame. Optional.
function TestBehavior.update(world, dt)
    local script_component = stingray.EntityManager.script_component(world)--SimpleProject.script_component
    if script_component == nil then
        return
    end
    local world_entity_data = world_data[world]
    for entity, entity_data in pairs(world_entity_data) do
       local com, num = script_component:instances_with_script(entity, "Test2Behaviour", query_cache)
       if num ~= 0 then
           print("AA"..num)
       end
       local ents = script_component:entities_with_script("Test2Behaviour")

        for script_component_instance, script_component_data in pairs(entity_data) do

            -- TODO: Do your component's update logic here.
        end
    end
end

script_component:instances_with_script

一応SimpleProjectのscript_componentを引いて使ってみたりもしたけど結果は変わらず。
Component間通信ができないと色々辛いのでなんとかしたい。

ちなみにUnity3dのMonoBehaviourと違って、全てstatic classやsingletonで書くようなイメージ。

このスクリプトを記述する上での留意点は、すべてのゲーム ワールドでモジュールが関連付けられている「すべての」エンティティを処理する必要があることです。このスクリプトで各エンティティに対して定義するコンポーネント オブジェクトの個別のコピーはなく、ゲーム内にはこの Lua オブジェクトのインスタンスは 1 つ だけあります

引用元:http://help.autodesk.com/view/Stingray/JPN/?guid=__stingray_help_using_entities_script_behavior_html

参考:ScriptComponentのドキュメント
http://help.autodesk.com/view/Stingray/ENU/?guid=__lua_ref_obj_stingray_ScriptComponent_html