近年メジャーなゲームエンジンの二大巨頭と言えば、 UnrealEngine (UE)と Unity3D (Unity)だ。特にUEはハイエンド用途1に強く、映像用2としても使われている。
最新バージョンのUE4系では、C++もしくはブループリントと呼ばれるビジュアルプログラミング環境でゲームロジックを開発する。前者は主にプログラマ、後者は主にゲームデザイナやアーティストが使用する。職種による使い分けという意味ではC#かUnityScriptしかないUnityに比べると明確で、とても分かりやすい設計になっている。
一方で、C++は複雑過ぎるけど、ブループリントは冗長、という考え方もある。ちょうど中間で気軽に書ける環境が欲しいという需要もある。
今回紹介する Unreal.js はJavaScriptでUE4を操る事が出来るプラグインだ。
Unreal.js
NCSOFTがリリースするプラグイン。V8をUE4のプラグインとして組み込み、UE4のC++ APIをラッパーを経由する事でたたく事ができる。ゲームロジックを記述する事はもちろん、エディター拡張と連携してツールをつくることもできる。
できること
- UE4のAPIへのアクセス
- 既存クラスやブループリントのクラスのサブクラス化にも対応するらしい
- UMGやSlateUIを使ったWidgetやエディタ拡張の作成も可能
- CommonJS + npm
- CommonJS方式のモジュール呼び出しに対応しているためnpmモジュール等が使える
- 型定義ファイル(d.tsファイル)の自動生成
- VSCode等でAPIの補完ができる
- 使用するレベルのマップで使っているAPIの型定義ファイルを自動生成できる
- ただし、間違った出力になっているので TypeScriptで使うには手を入れる必要がある3
- ライブリロード
- JSでコンソールコマンドやCommandletが書ける
- JavaScriptデバッガ連携
- V8プロトコルに対応
- ES2015対応
- UnityのJavaScript(ES4ベースのUnityScript)とは異なり、モダンで標準なJSが使える
面白い例としてはgistに置かれた外部JSファイルをランタイムに読み込んで実行する例などもある。
導入
必要環境:
- Windows 32/64-bit / (mac) OS X
- UnrealEngine 4.11.x - 4.13.x
-
Epic Game Launcherなどからマーケットプレイスにゆき、「
Code Plugins
」カテゴリもしくは「Unreal.js
」で検索してUnreal.jsを見つける -
「エンジンにインストールする」をクリックしてインストール
-
UE4を起動し、任意のプロジェクトを開く
-
「Edit」>「Plugins」を開きUnreal.jsがインストール済&有効になっていることを確認
プラグインが有効になると、Content/Scripts
ディレクトリが自動で生成される。JSはこの中に書いてゆくことになる(なお、コンテンツブラウザからはJSファイルを閲覧できない=Assetとして認識されない)。
Hello World
Javascript Console上でHello World
とりあえず一番かんたんな方法はREPLにもなる Javascript Console を使ってみることだ。
- 「Window」>「Developer Tools」>「Javascript Console」を選択
- 入力欄に「
console.log("Hello World")
」 と入力
- Hello Worldが出力される
レベル上でHello World
-
Content/Scripts
以下をExplorer/Finderで開き、空のJSファイルを作る
- とりあえず
helloWorld.js
- なお、おすすめのエディタはVisualScriptCode
- 以下のJSを書いて保存
let actor = new TextRenderActor(GWorld,{X:100,Z:100},{Yaw:180})
actor.TextRender.SetHorizontalAlignment('EHTA_Center')
actor.TextRender.SetText('Hello World')
-
UE4に戻り、新規のBlueprintクラスを作成する
-
Detailsタブで
Javascript
コンポーネントを検索&追加する
なお、このコードはライブリロードができない。ライブリロードは公式サンプルの中に含まれるHello Worldのようにtry-catch文で同梱のbootstrap.js
を呼ぶ処理を書く必要がある。
エディタ拡張WindowでHello World
Unreal.jsはエディタ拡張をつくることもできる。エディタ拡張版Hello Worldもやってみよう。
-
Content/Scripts
以下をExplorer/Finderで開き、extension
というprefixを付けたファイル名で新規jsファイルを作成- 例:
extension-helloWorld.js
- 例:
- 内容を以下にする
"use strict";
let I = require('instantiator')
let UMG = require('UMG')
let design = UMG(JavascriptWindow,
{
SizingRule:'AutoSized',
Title:'Hello World'
},
UMG(Button, {},
UMG.text({},"Hello World Window!")
)
)
I(design).TakeWidget().EditorAddModalWindow() //①
//I(design).TakeWidget().AddWindow() //②
ドキュメント
英語だが公式の動画チュートリアルやWikiが参考になる。日本語の情報は残念ながらほとんどない。
サンプルでさらっとやっていたり、githubのIssuesで回答がある内容もあったりするのでgithub内を根気よく探すと情報がでてくるだろう。
サンプルの解説
GoogleDrive / github以下にサンプルが用意されている。
現時点(2016-10-10)で一部うごかないものもあるが、いくつか紹介。
helloWorld.js
公式版Hello World。前述のとおりライブリロードに対応したコードがある。ライブリロードを聞かせるには bootstrap.js が必要(後述)。
なお、冒頭のue.d.tsへのリファレンスパスコメントは、実は最新のVSCodeでは不要。
bootstrap.js
サンプルの大半はこのファイルを使う想定で書かれている。
VSCodeなどで補完が効くのは、ue.d.tsがあるからだが、実際のレベル中に設置されたものにアクセスするには、実行中に一度JS中からContext.WriteDTS()
を呼ぶ必要がある。
bootstrap.jsは普段はコメントアウトされているが、コメントアウトを外して実行することでue.d.ts / aliases.jsを更新できる形になっている。
とりあえず、このファイルを流用しておくのが安定。
helloBlueprint.js
既存のBPクラスをJSで継承するサンプル。Unreal.jsではUPROPERTY
は独自期法で記述する形になっており、それのサンプルにもなっている。
extension-spiralGenerator.js
らせん状に並ぶMeshを生成するツールのサンプル。高機能なエディタ拡張のサンプルとなっている。コード量は多い。
helloProcess.js
要Node.js。Node.jsのプロセスを起動するサンプル。
helloUMG.js
UIを表示するサンプル。JSコンソール機能付き。
同梱ライブラリ・API
API
UEとのブリッジAPIはScripts/typings
以下の*.d.tsファイル群に定義されている。ただし、コメント等はないのでソースとUE4のドキュメントを参照して調べる必要がある。
同梱JavaScriptライブラリ
プラグインに同梱のJSライブラリが以下のパスにある。
Engine\Plugins\Marketplace\UnrealJS\Content\Scripts
lodashなどが含まれるほか、instantiator.js, UMG.jsなどサンプルでもよくつかわれるライブラリが含まれる。
で、実際どうなの?
- できることの印象
- UE4 C++ > Unreal.js > Blueprint
- 👍環境が用意しやすい
- プラグイン+テキストエディタ(VSCodeなど)で始められる
- 👎ドキュメントの充実具合は×
- 👏型定義ファイル生成機能があるのはいい
- 👎型情報の扱いがJSなのでビミョウ
- JSDoc式でもTypeScript式でもなくコメント内に独自記法
- 👍エディタ拡張が作りやすい
- UE4 C++は冗長&ビルドが必要、BlutilityはUIが作れない
- ノンビルドで、サクッと作れる
- NCSoftでもその用途に使っているらしい
- 👍コンソールコマンドやCommandletにも使える
- C++で組むより気軽で頻繁な変更に対応しやすい
- ゲームロジックに使うには…
- 出力プラットフォームむけにV8をビルドする必要がある
- Win/Mac/Linux/Androidはすでにある
- ランタイムにJSを読んで実行もできるらしい
--