[UE5]HMDを使わずにVRの動作確認をして開発速度を上げる

# はじめに

本記事は[Unreal Engine (UE) Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ue) その2の12日目の記事になります。

VR開発ではHMD（VRゴーグル）を頭にかぶって動作確認するものと思われがちです。（私もそう思ってました）
しかし、HMDを使わずに動作確認できるようにしたところ、様々な恩恵が得られて開発速度が爆上がりしたので、そのやり方をご紹介します。
（すでに似たような記事がありましたらごめんなさい）

:::note warn
注意
見た目や操作感など実際のHMDでの動作とは異なる点があるため、最終的な動作確認はHMDを使って行ってください。
あくまで開発途中の軽い動作確認用の用途になります。
:::

# HMDを使わずにVRの動作確認ができると何がいいの？

HMDを使わないことで、下記のような恩恵を受けられます。

- マルチプレイVRの動作確認が簡単にできる
- 動作確認に要する時間がかなり減る
- 頭皮のダメージが減る

一つずつ詳しく見ていきましょう。
細かい話は興味ないから実装方法をすぐに知りたいという方は、[実装方法](#実装方法)をご覧ください。

### マルチプレイVRの動作確認が簡単にできる

マルチプレイのVRコンテンツを開発している場合、これが導入をお勧めする一番の理由になります。
（UE4での体験になるので、もしもUE5から仕様が変わっていたらごめんなさい）

HMDを使ったVRプレビューでの動作確認の場合、複数人でのマルチプレイの設定で実行してもサーバーしかうまく操作することができません。
（HMDの動きがサーバーのみにしか反映されず、クライアントの視点は動かせません）

そのため、複数人プレイ時のクライアントの動きを確認したい場合、パッケージングして複数台のPCで動作確認するしかなく、非常に手間と時間がかかります。

HMDを使わずに動作確認する際はHMDの動きに縛られることがないので、サーバーもクライアントも自由に動かすことができてマルチプレイの動作確認を簡単に行うことができます。

### 動作確認に要する時間がかなり減る

HMDを使ったVRの動作確認では、下記のような流れの後に動作確認が開始できます。

1. VRプレビューボタンを押す
1. HMDを頭にかぶる
1. HMDのスリープが解除される
1. コントローラーを両手に持つ
1. コントローラーのスリープが解除される
1. 動作確認開始

これら一連の動作に1回の動作確認毎に数秒はかかります。

一方、今回説明する方法では上記の手順をかなり簡略化でき、下記のようになります。

1. プレビューボタンを押す
1. （ゲームパッドを使う場合）ゲームパッドを手に取る
1. 動作確認開始

これなら1秒もかからずに実行できるため、1日に何回何十回と動作確認していると、地味に開発速度に影響してきます。

### 頭皮のダメージが減る

動作確認で1日に何度もHMDの着脱をしていたときは、頭皮へのダメージも気になっていました。
HMDを外す際にたまにプチプチと髪の抜ける恐ろしい音が聞こえることも...
~~こんな生活を続けていたらハゲそう~~

HMDを使わない動作確認では、HMD着脱の回数がかなり減るので頭皮に優しく将来的にも安心です。

# 実装方法

実装に必要なのは下記の2点です。

- 操作用のキー設定を追加
- 頭と手の初期位置を変更

今回はUE5.1.0のVRテンプレートを使って説明します。

操作方法はキーボードやマウスでもいいのですが、今回はXInput対応のコントローラー（箱コン）を使う設定にします。
これは手を動かす際にアナログスティックを使ったほうが微調整しやすいためです。

### 操作用のキー設定を追加

UE5.1からVRテンプレートのキー入力の方法が変わって[Enhanced Input](https://docs.unrealengine.com/5.0/ja/enhanced-input-in-unreal-engine/)に変わっていたので、これを使ってやってみます。
（初めて使ったので間違っていたらご指摘ください）

まずは手を上下左右に動かすための入力設定を作ります。

コンテンツブラウザでVRTemplate/Input/Actionsの下にDebugフォルダを作成し、Input Action（入力アクション）を右手と左手用の2つ作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/2dafa7be-02f8-3ae1-5384-e120afc87b15.png)

中身はこのようになっていて、Value TypeをAxis2D(Vector2D)に変更しました。
今までは1軸（Float）のみの入力に対応していたものが、Enhanced Inputだと2軸や3軸（Vector）にも対応しているんですね、便利！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/4b5b9e38-51b2-a015-55be-6c5701f0c5cc.png)

コンテンツブラウザでVRTemplate/Inputにデバッグ用のInput Mapping Context（入力マッピングコンテキスト）の「IMC_Hand_Debug」を作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/e3847259-5a3f-7bf0-b26c-e94900bd8ec0.png)

中身はこのようになっていて、それぞれゲームパッド左右のサムスティックの2D軸を設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/a1f986b2-ca83-8054-6f6b-496760cb05c7.png)

この入力値を使って手を動かす設定を作ります。

コンテンツブラウザでVRTemplate/BlueprintsにあるVRPawnを開き、下記のようにノードを組みました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/f0a28d85-91ee-8e48-a158-51adfa1d53ed.png)

ついでに動作確認終了時にいちいちキーボードのEscキーを押すのが面倒なので、ゲームパッドの真ん中付近のボタン（プレステで言うところのOptionボタン、Switchで言うところの＋ボタン（箱コンでの呼び名が分からない...））を押したらゲームが終了するようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/08324c05-7858-0ef6-2d48-ebd4ea911c59.png)

次に、既存のボタンを箱コンのボタンに当てはめていきます。

今回は一例として、左右に回転する既存の機能を箱コンの十字キー左右で操作できるようにしてみます。
コンテンツブラウザでVRTemplate/InputにあるIMC_Defaultを開き、下記のように設定します。
十字キー左を押したときは-1の値が入力されてほしいので、ModifiersにNegateを入れました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/78fe03e4-202d-9519-9582-2b7318524ea9.png)

その他のボタンも同様に、必要に応じてコントローラーの好きなキーに割り当ててみてください。

### 頭と手の初期位置を変更

続いて頭と手の初期位置を変更します。

現在の状態で「新規エディタウィンドウ（PIE）」でプレビュー実行してみると、頭が地面に埋まった状態になり、手もどこにあるのかわかりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/a0d5382a-534e-bbdd-f0ff-e4740f3d6729.png)

HMDを使わずに起動したときは頭と手の位置を変更するようにしたいです。

HMDを使っているかどうかの状態を取得するには、「Is Head Mounted Display Enabled」ノードを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/0b6c1724-4590-4873-a370-6c89b102b4c5.png)

今回はVRPawnのBeginPlayに既に「Is Head Mounted Display Enabled」ノードが使われているので、ここのFalseからノードを繋いでHMDを使わない場合の設定をしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/6f733c19-83bf-747c-9083-3f8ed0c455f3.png)

設定内容としては、頭（Camera）と手（Motion Controller Right/Motion Controller Left）の位置を変更して、先ほど作成したInput Mapping Context（入力マッピングコンテキスト）の「IMC_Hand_Debug」を使えるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/3be15e4d-68da-534b-7171-09fb8772ebdb.png)

ノードの最後は既存のInput Mapping Contextの初期設定に接続して、その他のキー操作ができるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/d6a38fd9-ce94-c4f6-e29a-3ee3631618fe.png)

以上で、手を上下左右に動かす、体を左右に回転させるという限定的な機能だけですが、HMDを使わずにVRの動作確認ができるようになりました。

https://twitter.com/abricheese/status/1602141581493968897

その他の操作も同様にして追加していき、一通りVRと遜色ない操作ができるようになれば、かなり開発効率を高めることができるのではないかと思います。

特定のボタンを押している間だけアナログの動作が変わるようにしておくのが個人的にはおすすめです。
例：
Aボタンを押している間はアナログスティック上下で手が前後に動く、Bボタンを押している間は手が回転する等

また、プレイヤー数を増やしてネットモードを「Play As Listen Server」や「Play As Client」にするとマルチプレイの動作確認もできます。
（VRテンプレートはマルチプレイ対応できていないので、正しく動作はしないですが...）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/0cdda8ac-f057-2774-d3b6-af0bf2ac74d3.png)

他にもVRプレビューでは使えない、「選択ビューポート」で実行してF8キーを押してレベル上のアクターの状態をアウトライナーで確認するという技も使えるので便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/09211015-d672-c693-8475-a4ecdca2f04c.png)

以上で説明を終わります。
よきVR開発ライフを！