UE4用AngelScriptPluginを公式ビルド版UE4に持ち込んでみた。

プラグインだけ抜き出して公式ビルドで使えないのかと思って試してみた。
結論からいうと、できませんでした。

Unknown function specifier 'ScriptCallable'

プラグインだけ抜き出してきてもScriptCallableというものが見つからずビルドできない。

公式ドキュメントを見てみると、
ScriptCallableというものがAS版UE4では追加されている。
https://angelscript.hazelight.se/cpp-usage/

AngelScriptからC++側のUFunctionを見えるようにする指定のようだ。
この他、BlueprintCallable/BlueprintPure の指定がされているUFunctionも自動的にバインドされる模様。

BPからは見えないが、ASからは見えるモジュールを作るときにScriptCallableを使うということらしい。

次回はマーケットプレイスのソース付きプラグインをAS版UE4に持ち込んでみる予定。
BPから見えるC++モジュールはおおよそASから見える、というイメージだけれど
どれだけ叩けるものなのか。

LGUI (Lex GUI)について雑多なメモ

LGUI (Lex GUI) - 3D UI System for UE4:liufei:Code Plugins - UE4 マーケットプレイス

UnityのUGUIに慣れた人向けに作られたプラグインです。
UMGに比べてパフォーマンス的にも有利になりそう?
ソース付き。

今ひっかかってるところ。

  • DX12モードでエディタを起動したらUISpriteが見えなくなった(文字は見える) 。 ↑20191009追記。UE4.23かつ最新版プラグインでは問題なし。4.22系のままプラグインを最新にしたらサンプル内のBPがあちこちエラー。操作まわりだったのでおそらくレンダリングには関係ないと思われるため取り除いたが、やっぱり4.22.8でのレンダリングはおかしいままだった。UE側の問題だったのかも?

  • サンプルをビルドしたらPrefabがロードできなかった(エディタではロードできる)。Cookの設定?

  • スケーリング機能が無いっぽい?かわりにheight,widthを操作するっぽいけど....(9/2 追記)
  • Tweenはコード上からしか生成できない?

新規UIの追加方法
ツールバーの起動の隣あたりにLGUI Toolsという項目が追加される。
小さいアイコンにする設定の場合、アイコンの絵だけ表示されないので注意(メニュー自体は使えます)
そこからBasic Setupを選ぶ。2DならScreen SpaceUI、3DならWorld SpaceUIを選択。 f:id:eims:20190827022743p:plain:w200f:id:eims:20190827022609p:plain:w200

2DUIのプレビューの仕方
Overlay_SceneCapture2D(作成したUIのルート)をアウトライナで右クリックして「パイロット」
プレイしたときに比べて小さく表示されることがあったので、もうちょっと何かいい方法があるのかも... ↑20191009追記。最新版ではできないらしい。

マスク
UIPanelにクリッピングの設定があるので、たぶんこれだろう。
飛行機が写っているサンプルではこれを使っているようだ。
f:id:eims:20190827021624p:plain:w200

日本語について
文字表示は問題なさそう
ちゃんと反映されたことがわかりやすいようにフォントは↓の限界明朝でテスト
https://flopdesign.com/blog/font/5146/

f:id:eims:20190827024529p:plain:w200
エディタ内で試しただけだけれど、TextInput(入力窓)での日本語入力も問題なしでした。
f:id:eims:20190827025542p:plain:w200

近いうちに素材適当に選んでちゃんと実践したい。

UE4用のAngelScriptバインディングを試した

公式サイト
リポジトリ

リポジトリのアクセスにはUE4の公式リポジトリへのアクセス権があるアカウントが必要。
スクリプトの編集はVSCodeと独自のVSCode拡張を使う。
AngelScriptを使ってActorなどの追加が可能。
ビルド済みのバイナリはリポジトリのリリースページで配布されています。
VSCodeスクリプトを編集、UE4エディターに戻るともう反映されている。
ログの日本語出力ができなかったのだが、日本語まわりの対応は怪しいかもしれない。
(UMGなんかと接続してみないと、なんともいえないが...)

// For example, we can make a new Actor class
class AExampleActorType : AActor
{
    /* Any class variables declared as UPROPERTY() will be
    * accessible to be set in levels on the actor. */
    UPROPERTY()
    int ExampleValue = 15;

    /* Use the 'default' keyword to override property defaults from the parent class. */
    default bReplicates = true;
    default Tags.Add(n"ExampleTag");

    /*
    * Methods without UFUNCTION() will only be usable from script.
    *  Since unreal does not need to know about them, hot reloading them
    *  can occur significantly faster than when a UFUNCTION() changes.
    */
    void ScriptOnlyMethod()
    {
        Log("ごはんだーいすき"); << エディタ上では??????表示
        Log("ScriptOnlyMethod Called");
    }

あまり掘り下げできていないが今日はここまで!

追記

f:id:eims:20190819000416p:plain
FStringなプロパティも化けた。
日本語コメントはできる。 UE4側からFStringプロパティに日本語書き込んで、AngelScriptのPrintで吐くのは大丈夫っぽい。

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

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

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 crafted game engine
注目しているが、まだごく初期段階。
とりあえずワクワクできるのでアクセスしてみてほしい。

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

ShiVa Engine – Cross-platform Game Engine and IDE 1.9系はluaまわりがイマイチだった記憶。
2.0ではどうなのか?

Zero Engine Hub | Changing Onlein Gaming in 3D Evolution DigiPenが開発中のゲームエンジン。 現状はPC専用?

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

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

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

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


2019年5月追記

https://flaxengine.com/ www.youtube.com メモ(


2020年3月追記

https://www.layabox.com/
LayaAir。HTML5向け。 描画やUI構築の機能は一通りありそう。 ドキュメントや公式サイトの言語が壁。 ソースは公開されているが、ライセンスの言語も...


2020年4月追記

https://ourmachinery.com/
BitSquid,Stringrayの開発者が作っている新ゲームエンジン
初期ベータ段階。


2020年7月追記

SDK Editions And Pricing | UNIGINE: real-time 3D engine
ゲームエンジンでありながらあまりゲームエンジンを志向してない印象。
エンジニアリング用途のライセンスではQtやWPFと連携できたりする。

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ということに気付きました。
メッセージなどはスクリプト側に書けませんね。