Unreal Engine 4 + Oculus Rift + Touch でVRコンテンツを作成する

# この記事で目指すもの
次の要件を満たす簡単なコンテンツを、Unreal Engine 4(以下UE4)で作成します。使用するVRヘッドセットはOculus Rift、コントローラーはOculus Touchとします。

* ヘッドセットをかぶるとゲームの世界に入れる
* Oculus Touchを現実と同じ位置に表示する
* Oculus Touchのボタン入力を受け取る

なお、この記事で使用しているUE4のバージョンは 4.16.2 です。

# 準備
## プロジェクトを作成する
UE4を起動し、新規にプロジェクトを作成します。
VRのテンプレートが目を引きますが、今回は「空のプロジェクト」を選択します。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/0d4ffdf3-41b5-4c36-6dd1-711e174a454c.png)

## プラグインを有効化する
メニューバーの編集 -> Pluginsから、Virtual Realityを選択し Oculus Input, Oculus Library, Oculus Rift のプラグインについて Enabled にチェックが入っていることを確認します。入っていなければチェックを入れます。
![プラグイン.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/5b24c727-63af-4c5f-3fdc-0c021b8a33a6.png)


# ヘッドセットに対応する
## StarterContent のレベルをヘッドセットで見る
VRモードでゲームをプレイするだけです。
(ここでは、StarterContentに入っている Minimal_Default を使用しています)

プレイの横のプルダウンをクリックした後、「VRプレビュー」を選択します。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/83524/b2eff0cd-8bb7-26fd-61d5-385b2c3598f0.png)


プレイボタンを押して、ヘッドセットをかぶってみましょう。見渡してみると、ビューポートに表示されていたゲームの世界が一面に広がっており、実際にそこにいる感覚を味わうことができるでしょう。
マウスやキーボードのWASDの入力による視点操作が効いてしまいますが、一旦置いておきます。

## Pawn を配置する
PlayerStartだけでは、「見る」以外に何もできません。
そこで、PlayerStartの代わりに **ヘッドセットをかぶった自分自身を表すプレイヤーアクタ** を作成します。このプレイヤーを表すアクタのことをUnreal Engine 4では Pawn と呼びます(英語で「操られるもの」を意味しています)。
これにより、後で説明する「Oculus Touchを認識させる」「Oculus Touchのボタン入力を受け取る」ことができるようになります。

### Pawn を作成する
コンテンツブラウザで右クリックし、ブループリント クラスを選択します。
![blueprint.png](https://qiita-image-store.s3.amazonaws.com/0/83524/520f8ce6-6980-9fed-b92b-7b729fd7ab98.png)

親クラスとして、Pawn を選択します。
![blueprint2.png](https://qiita-image-store.s3.amazonaws.com/0/83524/544ca800-68f2-995e-e7ac-4b34206b98ff.png)

これでコンテンツブラウザ上に新しいブループリントができたと思います。ここでは名前を VRPawn としておきます。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/19312a9d-010e-2e75-199f-2d94bc476d89.png)

次に、作成したVRPawnをダブルクリックしてブループリントエディタを開きます。
コンポーネントタブにて DefaultSceneRoot が選択されている状態で、「コンポーネントを追加」をクリックし、コンポーネント一覧から Camera を探し、クリックします。
![blueprint3.png](https://qiita-image-store.s3.amazonaws.com/0/83524/34d59ac9-85bc-ae31-ab1c-1bc6b0b6dd81.png)

ビューポートにカメラが追加されました。
この状態でVRPawnを保存し、ブループリントエディタを閉じます。
![camera.png](https://qiita-image-store.s3.amazonaws.com/0/83524/ce693ad3-0b54-ae62-c6fb-b7ded4a5fb7e.png)

### 作成した Pawn を配置する
先ほどヘッドセットで見たレベルにて、PlayerStartを削除し、作成したVRPawnを適当な位置に配置します。
![level.png](https://qiita-image-store.s3.amazonaws.com/0/83524/57f59496-7c95-079f-4a78-37c8198fbcd0.png)

この状態で再生すると、PlayerStartを配置した場合と同様にゲームの世界をVRで見ることができますが、相変わらずマウスやキーボードの入力が効いてしまっています。
これは、詳細パネルのPawnカテゴリにある Auto Process Player で、Player 0 を設定することにより解消されます。設定した後にレベルを保存して、プレイしてみましょう。
(Player x のxは Player Index と呼びます。ここでは詳しく説明しません)
![player.png](https://qiita-image-store.s3.amazonaws.com/0/83524/7d782ecf-52a0-3af5-a348-f67baea66f22.png)

# Oculus Touch をゲーム上で表示させる
Oculus Touchの位置を認識し、そこにOculus Touchのコントローラーを表示させます。

## Motion Controller を配置する
Motion Controller は、Oculus Touchなどのコントローラーを表しています。Motion Controllerが持つ座標は現実世界におけるコントローラーの位置に基づいており、これによりゲーム中でもコントローラーを追従することができます。

VRPawnをダブルクリックして、ブループリントエディタを開きます。
DefaultSceneRootの直下(Cameraと同じ階層)に、コンポーネント MotionController を2つ追加します。Cameraを配置した時と同様に、「コンポーネントを追加」からMotionControllerを探しましょう。
名前はそれぞれ MotionControllerL, MotionControllerR とします。
![motioncontroller.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/7f7bcd8f-88c9-e1da-3680-8decee334a3b.png)

MotionControllerLについて、詳細タブのMotion Controller カテゴリにある Hand が Left に設定されていることを確認します。
MotionControllerRについてはこのHandを Right に変更します。
![left.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/a965ce1c-4ce8-59bf-1fb3-8c6a7c7d899e.png)
これでMotion Controllerの準備は完了です。

## Motion Controller の子孫にコンポーネントを配置する
Motion Controllerを配置するだけでは、コントローラーをゲーム上で表示させることはできません。Motion Controllerが持っているのは、コントローラーの位置や角度などの情報しか持っておらず、視覚的な情報を持っていないからです。
コントローラーを表示するには、Motion Controllerの子孫の階層にオブジェクトを配置する必要があります。Motion Controllerの子孫のオブジェクトは、親であるMotion ControllerのTransformに依存しています。つまり、Motion Controllerが動くと、それに追随して子孫のオブジェクトも動くのです。

では、Motion Controllerの子孫にOculus TouchのStatic Mesh Componentを置いてみましょう。
再度VRPawnのブループリントエディタを開きましょう。

エンジンコンテンツ -> VREditor -> Devices -> Oculus にある、OculusControllerMesh を、MotionControllerLとMotionControllerRの直下にドラッグ&ドロップします。
または、「コンポーネントを追加」から「スタティックメッシュコンポーネント」を探してMotionControllerLとMotionControllerRの直下に配置し、詳細タブのStatic MeshにOculusControllerMeshを入れます(画像参照)。
![staticmesh.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/bdb4def2-9fc1-534c-8e4d-e527cd753ab6.png)

エンジンコンテンツがコンテンツブラウザから見えない場合は、コンテンツブラウザの右下にある「表示オプション」をクリックし、「エンジンコンテンツを表示」にチェックを入れると見えるようになります。
![visiblecontents.png](https://qiita-image-store.s3.amazonaws.com/0/83524/b5362c96-823f-91ba-1c36-00678deccb8b.png)

配置した結果、以下のような階層構造になります(ここでは OculusTouchL, OculusTouchR と名前をつけています)。
![oculus.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/0a7cccac-c9a8-59cc-de6c-fbb5e8b24456.png)


エンジンコンテンツで提供されているOculusControllerMeshは、左手用のものしか提供されていません。
![oculusL.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/c49bf0ba-7bb4-6363-309d-f792107fe771.png)
そこで、OculusTouchRを右手用のものに変更します。
上の画像の緑色の矢印(Y軸)の方向にScaleを反転することで、OculusControllerMeshも反転して右手用のものになります。OculusTouchRのトランスフォームにて、Scale(拡大・縮小)のYの値を 1.0 から -1.0 に変更しましょう。
![oculusRtransform.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/ca63ad31-f085-59a2-f766-0f8efe1c07e7.png)

反転して右手用のものに変わります。
![oculusR.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/8d443cb3-c320-a8cd-388e-3f878256d50d.png)

以上で完了です。ヘッドセットをかぶってプレイしてみましょう。
手元を見ると、Oculus Touchが見えているはずです。

# Oculus Touchのボタン入力を受け取る
Oculus Touchのどのボタンが押されたらどうする、というイベントを記述することができます。
VRPawnのブループリントエディタを開き、ビューポートではなく「イベントグラフ」のタブをクリックして開きます。

## トリガーの入力を受け取る
ここでは、「Oculus Touchのトリガーボタンを押したらOculus Touchの位置に球を出現させる」というものを作ってみます。

ブループリントエディタにて、イベントグラフの何もない任意の場所を右クリックし、MotionController(L) Trigger を探します。
直接検索するか、「インプット」->「ゲームパッドイベント」から探すことで見つかります。
見つかったら、MotionController(L) Trigger をクリックします。最初に右クリックした付近に画像のようなノードが配置されます。
![node.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/0e13f3cd-ef7c-79cc-da72-9a340ae9a49a.png)

配置したノードにつなげるイベントを書く前に、出現させる球のActorを以下のように適当に作ります。
ここでは、Sphereを(0, 0, 0)の位置に置き、大きさを調整して適当にStarterContentに入っているマテリアルを貼りつけました。
![SampleActor2.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/4b2075bb-175b-5588-b132-1fa5cf889e4e.png)

![SampleActor1.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/96ff97c8-c03d-481b-e801-0b982de73d96.png)

上で作成したActorをOculus Touchの位置に出現(Spawn)させる処理を入れ、MotionController(L) Trigger の Pressed から実行ノードをつなぎます。下の画像のようになります。
![nodes.PNG](https://qiita-image-store.s3.amazonaws.com/0/83524/5368e2c5-e46e-adcd-7c36-99bf30bb9995.png)

プレイしてみましょう。左手のトリガーを押すと作成したActorがその場に出現するはずです。
右手にも同様の処理を入れてみましょう。

## その他の入力イベント
英語ですが、以下のリンクを参照してください。A, B, X, Yボタンの対応付けが少し分かりにくいと思います。
https://forums.unrealengine.com/showthread.php?131000-Unreal-Button-Mapping-names-for-Oculus-Touch&p=644385&viewfull=1#post644385

また、Oculus Touchにはボタンやスティックを押すのではなく触ったという判定も検知することができ、Unreal Engine 4においても対応するイベントが用意されています。
![touch.png](https://qiita-image-store.s3.amazonaws.com/0/83524/42cba1af-dcfc-2c77-cd31-06eb597e391a.png)


# 最後に
簡単にですが、Unreal Engine 4でOculus Touchを使ったVRコンテンツ作成のために最低限必要なものを書きました。
本記事では扱いませんでしたが、[仮想現実 （VR） のベスト プラクティス](https://docs.unrealengine.com/latest/JPN/Platforms/VR/ContentSetup/index.html) は読んでおきましょう。