Help us understand the problem. What is going on with this article?

[UE4]Unreal.jsでJSのコードに型とフラグ情報を付与する

More than 3 years have passed since last update.

Unreal.jsプラグインでJavaScriptで作成したものをUE4の世界に認識させるには次の方法が必要になる。

  1. ES2015(ES6)の書き方でクラスを生成
  2. クラス・メソッド・プロパティに 型とフラグの情報を付与
  3. uclass.jsで型とフラグ情報を解析させてUE4側にクラスを認識させる

この「型とフラグの情報を付与」という部分が若干特殊なので説明。

Unreal.jsでの型およびフラグ情報の独自表現

周知の通り、JavaScriptには型表現の方法が基本的にない。一方UE4のUnreal C++ & Blueprintには型がある。Unreal.jsではこの差を埋めるために、コメント中に埋め込まれた型とフラグ情報を解析した上でUE4側に渡す形になっている。

また、Unreal C++独自のマクロ(UPROPERTYなど)での識別子指定もフラグ情報等として表現できる( メタデータ識別子 メタプロパティも一部対応しているようだ)。

以下が、それぞれのUnreal C++マクロに対応するJS側での書き方。

UCLASS

unreal_c++
UCLASS([specifier, specifier, ...], [meta(key=value, key=value, ...)])
class ClassName : public ParentName
{
    GENERATED_BODY()
}
class ClassName /* ClassFlag+ClassFlag+... */ extends ParentClass {
   ctor() {
     // initialization
     // component setup
   }
   properties() {
     // property-declarations
   }
}

class クラス名 /* フラグ情報1+フラグ情報2+... */ {}の形で定義する。

注意点:

  • ES5以前の疑似クラス定義には非対応
    • 文字列解析で処理されているため
  • コンストラクタはctor()
    • ES2015のconstructor()はJS側のコンストラクタ、ctor()はUE4側のコンストラクタとして働く
  • プロパティ(UPROPERTY)はproperties()で定義
  • UClassとして扱うには最後にuclass.jsで解析する必要がある
//transformed into corresponding USTRUCT and UCLASS
let cls = require('uclass')()(global, ClassName);

参考:USTRUCT and UCLASS

UFUNCTION

unreal_c++
UFUNCTION([specifier, specifier, ...], [meta(key=value, key=value, ...)])
ReturnType FunctionName([Parameter, Parameter, ...])
class ClassName{
  //...
  FunctionName([
    Parameter /* PropertyFlag+ParamType */,
    Parameter /* PropertyFlag+ParamType */,
     ... 
  ]) /* specifier+ReturnType */
}

前提としてUCLASSと同時に定義する必要がある(JS的には必ずクラスのメソッド)。

関数名(引数名 /* UPROPERTYのフラグ+引数の型 */) /* UFUNCIONのフラグ+返り値の型 */という形で定義する。「UFUNCIONのフラグ」は関数指定子ということで調べられるが、Unreal.jsのWikiには言及がないのですべて使えるかどうかは不明。

UPROPERTY

unreal_c++
UPROPERTY([specifier, specifier, ...], [meta(key=value, key=value, ...)])
Type VariableName;
Unreal.js
class MyClassName{
  //...
  properties(){
    this.VariableName /* specifier+specifier+...+Type */;
  }
}

前提としてUSTRUCTUCLASSと同時に定義する必要がある。

UPROPERTYマクロは変数プロパティをエディタ上やBlueprint上から扱えるように設定するため設定する頻度が高い。JSで同様にするためにはproperties()メソッドの中で次のように定義する。properties()メソッド以外では定義できないので注意。

this.プロパティ名 /* フラグ1+フラグ2+...+型 */;

なお、ドキュメントには明記されていないがEditConditionなどのメタプロパティも次のような書き方で有効になった。

metaの書き方
properties() {
  //bEditConditionが有効ならエディタ上で編集可能に
  this.EditConditionVariable /* EditAnywhere+Category:condition+EditCondition:bEditCondition+int32*/
  //エディタ上で普段は隠しておく
  this.bEditCondition /* EditAnywhere+Category:condition+AdvancedDisplay+bool */;  
}

MetaEditCondition1.png

MetaEditCondition2.png

USTRUCT

unreal_c++
USTRUCT([Specifier, Specifier, ...])
struct StructName
{
    GENERATED_USTRUCT_BODY()
};
class StructName /* Struct+Specifier+Specifier+... */{
   properties() {
     //property-declarations
   }
}

UStructはJSのクラスを作成したうえで、Structとコメントの最初に記述する。

参考:USTRUCT and UCLASS

補足情報

  • uclass.jsの中では正規表現で文字列解析して変換している
    • Function.toString()でソース文字列を引っ張って解析(コメントも取得できる)
    • なのでここのコードを書き換えるか同様の処理を別のJSでやれば別の記法で型とフラグ情報を付与できる
  • UINTERFACEマクロに相当するものはないっぽい?
ConquestArrow
ノンプログラマです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away