Unreal.js 入門

![Unreal.js.png](https://qiita-image-store.s3.amazonaws.com/0/54764/05efae52-387c-2af1-ae7a-7481e6a0b55f.png)


近年メジャーなゲームエンジンの二大巨頭と言えば、 **UnrealEngine** (UE)と **Unity3D** (Unity)だ。特にUEはハイエンド用途[^1]に強く、映像用[^2]としても使われている。

最新バージョンのUE4系では、C++もしくは[ブループリント](http://qiita.com/tags/Blueprint)と呼ばれるビジュアルプログラミング環境でゲームロジックを開発する。前者は主にプログラマ、後者は主にゲームデザイナやアーティストが使用する。職種による使い分けという意味ではC#かUnityScriptしかないUnityに比べると明確で、とても分かりやすい設計になっている。

一方で、C++は複雑過ぎるけど、ブループリントは冗長、という考え方もある。ちょうど中間で気軽に書ける環境が欲しいという需要もある。

今回紹介する **[Unreal.js](https://github.com/ncsoft/Unreal.js)** はJavaScriptでUE4を操る事が出来るプラグインだ。

# Unreal.js

[NCSOFT](http://www.ncsoft.jp/)がリリースするプラグイン。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ファイルをランタイムに読み込んで実行する例](https://github.com/ncsoft/Unreal.js/wiki/Running-from-gist)などもある。

## 導入

必要環境:

 * Windows 32/64-bit / (mac) OS X
 * UnrealEngine 4.11.x - 4.13.x


 1. Epic Game Launcherなどからマーケットプレイスにゆき、「`Code Plugins`」カテゴリもしくは「`Unreal.js`」で検索してUnreal.jsを見つける
    * ![UE_marketplace_unrealjs.png](https://qiita-image-store.s3.amazonaws.com/0/54764/41532a99-1637-fe96-c8c0-791307f497b8.png)

 2. 「エンジンにインストールする」をクリックしてインストール
    * ![install_unrealjs.png](https://qiita-image-store.s3.amazonaws.com/0/54764/054a2eb6-a421-d52e-44d5-063220f1c3a8.png)
 3. UE4を起動し、任意のプロジェクトを開く
 4. 「Edit」＞「Plugins」を開きUnreal.jsがインストール済＆有効になっていることを確認
    * ![Plugins_installed_unrealjs.png](https://qiita-image-store.s3.amazonaws.com/0/54764/428098d5-c32e-9ac1-4c2d-a0871e7a85bc.png)

プラグインが有効になると、`Content/Scripts`ディレクトリが自動で生成される。JSはこの中に書いてゆくことになる（なお、コンテンツブラウザからはJSファイルを閲覧できない＝Assetとして認識されない）。

![Unrealjs_script_folder.png](https://qiita-image-store.s3.amazonaws.com/0/54764/ec274a96-1829-aea7-fe8c-58524d8d0438.png)


## Hello World

### Javascript Console上でHello World

とりあえず一番かんたんな方法はREPLにもなる **Javascript Console** を使ってみることだ。

 1. 「Window」＞「Developer Tools」>「Javascript Console」を選択
   * ![OpenJSConsole.png](https://qiita-image-store.s3.amazonaws.com/0/54764/132429d2-9c8e-8aab-8cc5-13e95eda1af8.png)
 
 2. 入力欄に「`console.log("Hello World")`」 と入力
   * ![JSC_helloworld.png](https://qiita-image-store.s3.amazonaws.com/0/54764/f2381025-ff42-c649-e92a-339deb3530d1.png)
   * ※なお、テキスト補完も効く
 3. Hello Worldが出力される
   * ![JSC_helloworld2.png](https://qiita-image-store.s3.amazonaws.com/0/54764/ac6dd1c6-f824-d9f6-7f50-f955d1bf2a4b.png)



### レベル上でHello World

 1. `Content/Scripts`以下をExplorer/Finderで開き、空のJSファイルを作る
   * とりあえず `helloWorld.js`
   * なお、おすすめのエディタはVisualScriptCode
 2. 以下のJSを書いて保存


```js:helloWorld.js
let actor = new TextRenderActor(GWorld,{X:100,Z:100},{Yaw:180})
actor.TextRender.SetHorizontalAlignment('EHTA_Center')
actor.TextRender.SetText('Hello World')
```

 3. UE4に戻り、新規のBlueprintクラスを作成する
    * とりあえず今回は`Actor`を継承する
    * ![Unreal-js_Actor1.png](https://qiita-image-store.s3.amazonaws.com/0/54764/36f1c89b-761a-9796-c180-48abaf6e3a30.png)

 4. レベル上に今作ったBPクラスをD&Dする
 　* ![Unreal-js_Actor2.png](https://qiita-image-store.s3.amazonaws.com/0/54764/2d58504a-5a75-2a56-043c-762a8ce32eff.png)

 5. Detailsタブで`Javascript`コンポーネントを検索＆追加する
   * ![Unreal-js_Actor3.png](https://qiita-image-store.s3.amazonaws.com/0/54764/123611d1-f3ec-5153-9c69-b99d50fccb32.png)

 6. 「 **Script Source File** 」にさきほどのJSファイル名を入力
    * 例だと「`helloWorld.js`」
    * ![Unreal-js_Actor4.png](https://qiita-image-store.s3.amazonaws.com/0/54764/3ce92be8-07ec-92de-f031-f9141a521eb1.png)

 7. Playしてワールドに3Dの文字列が表示されるのを確認できればOK
    * ![Unreal-js_Actor5.png](https://qiita-image-store.s3.amazonaws.com/0/54764/96ea75ce-0067-70e9-91f3-42740c94da6f.png)

なお、このコードはライブリロードができない。ライブリロードは[公式サンプルの中に含まれるHello World](https://github.com/ncsoft/Unreal.js/blob/master/Examples/Content/Scripts/helloWorld.js)のようにtry-catch文で同梱の`bootstrap.js`を呼ぶ処理を書く必要がある。

## エディタ拡張WindowでHello World

Unreal.jsはエディタ拡張をつくることもできる。エディタ拡張版Hello Worldもやってみよう。

1. `Content/Scripts`以下をExplorer/Finderで開き、`extension`というprefixを付けたファイル名で新規jsファイルを作成
    * 例：`extension-helloWorld.js`
2. 内容を以下にする

```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()    //②
```

 1. UE4を起動し、以下のWindowが開けばOK
    1. ![unreal-js_hello_extension.png](https://qiita-image-store.s3.amazonaws.com/0/54764/b5e9746b-2917-2e9f-e6be-459e517717b1.png)
    2. なお、②を有効にすると以下のウィンドウがでる
       * ![unreal-js_hello_extension2.png](https://qiita-image-store.s3.amazonaws.com/0/54764/9b21a70f-f06d-bc27-fb02-35e3d4419503.png)



## ドキュメント

英語だが公式の動画チュートリアルやWikiが参考になる。日本語の情報は残念ながらほとんどない。

 * [動画チュートリアル](https://www.youtube.com/watch?v=XxPSLjBg7DU)
 * [wiki](https://github.com/ncsoft/Unreal.js/wiki)

サンプルでさらっとやっていたり、githubのIssuesで回答がある内容もあったりするのでgithub内を根気よく探すと情報がでてくるだろう。


## サンプルの解説

GoogleDrive / github以下にサンプルが用意されている。

https://drive.google.com/file/d/0B8EsJUQpOkucRVJna3dEczJHN2M/view

現時点（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

![Unreal-js_spiralgen.png](https://qiita-image-store.s3.amazonaws.com/0/54764/9f50a9d7-989c-e703-eb31-8a5a4422908e.png)


らせん状に並ぶMeshを生成するツールのサンプル。高機能なエディタ拡張のサンプルとなっている。コード量は多い。

### helloProcess.js

要Node.js。Node.jsのプロセスを起動するサンプル。

### helloUMG.js

![Unreal-js_helloUMG.png](https://qiita-image-store.s3.amazonaws.com/0/54764/83f516d7-a803-6f34-c619-d46b2d8046c2.png)


UIを表示するサンプル。JSコンソール機能付き。

## 同梱ライブラリ・API

### API

UEとのブリッジAPIは`Scripts/typings`以下の*.d.tsファイル群に定義されている。ただし、コメント等はないので[ソース](https://github.com/ncsoft/Unreal.js-core/tree/5.1.300/Source)と[UE4のドキュメント](https://docs.unrealengine.com/latest/INT/API/index.html)を参照して調べる必要がある。

### 同梱JavaScriptライブラリ

プラグインに同梱のJSライブラリが以下のパスにある。
`Engine\Plugins\Marketplace\UnrealJS\Content\Scripts`

lodashなどが含まれるほか、instantiator.js, UMG.jsなどサンプルでもよくつかわれるライブラリが含まれる。

# で、実際どうなの？

* できることの印象
 * UE4 C++ > Unreal.js > Blueprint
* 👍環境が用意しやすい
 * プラグイン＋テキストエディタ（VSCodeなど）で始められる 
* 👎ドキュメントの充実具合は×
 * 👏型定義ファイル生成機能があるのはいい
* 👎型情報の扱いがJSなのでビミョウ
 * [JSDoc式でもTypeScript式でもなくコメント内に独自記法](http://qiita.com/ConquestArrow/items/6c1eac9226aeb5ce2794)
* 👍エディタ拡張が作りやすい
 * UE4 C++は冗長＆ビルドが必要、BlutilityはUIが作れない
 * ノンビルドで、サクッと作れる
 * NCSoftでもその用途に使っているらしい
* 👍コンソールコマンドやCommandletにも使える
 * C++で組むより気軽で頻繁な変更に対応しやすい 
* ゲームロジックに使うには…
 * 出力プラットフォームむけにV8をビルドする必要がある
 * Win/Mac/Linux/Androidはすでにある
 * ランタイムにJSを読んで実行もできるらしい


--

[^1]: いわゆるAAAタイトル。FF7リメイクがUE4を採用したのは記憶に新しい。
[^2]: 最近で言えばドラマ版デスノートのリュークがUE4で作られた映像だ。
[^3]: TypeScriptでUnreal.jsを扱う方法については別の記事でまとめたい。