UE4でOculusQuest2を動かす２

# 初めに
　今回の記事は[前回](https://qiita.com/HnniTns/items/57e1c9ade062d85a8972)の続きです。出来れば前回の記事を見た上で、今回の記事を見るようにして下さい。
　この記事を書いている人は、VR開発については全くの初心者で、普通に間違っている可能性も十分にあるので、その点に関してはご了承ください。

追記：[第3回](https://qiita.com/HnniTns/items/0266f18586d1726a94c0)を上げました

# 入力関係
　入力関係が非常にややこしいと思ったので、ここに書いておきます。というのも、初見だと「トリガー？サムスティック？タッチ？グリップ？ なるほど...分からん。」になる可能性大だと思います。

## インプットの種類
　初見で見たとき「Oculusの入力３項目あるじゃん。どれだよ！」となりました。といっても、結局使うのは「**Oculus Touch**」になります。
　ちなみに、**エディタ上では「ヘッドセットを覗き込むか、ヘッドセットの検知部分を手で押さえるか」しないと入力状態になりません**。例えば、``PrintString``でデバッグするなら、ヘッドセットの検知部分を手で押さえて、画面を見て確認することになると思います。[^0]

[^0]: ちゃんと、ヘッドセット上でも表示はされますが、「かなり」左上の端なので非常に見にくいです。素直に画面を見た方がデバッグしやすいです。

### Oculus Touch
　通常ではこの欄を使います。この欄を展開すると絶望の種類数が待っています。ですが...頑張って覚えましょう。簡易的なゲームの場合、必要な入力数はそんなに多くないと思います。
　順番は「[oculus FOR DEVELOPERS - Oculusコントローラー入力のマッピング](https://developer.oculus.com/documentation/unreal/unreal-controller-input-mapping-reference/)」におおよそ準じます。~~このサイト説明が複雑怪奇（ry~~
　後、画像はOculusQuest2ではないですが、ほぼ同じなので気にしないで下さい。UE4のエンジンに入ってるモデルをスクショしたものです。

#### ・サムスティックのタッチ、プレス、サムアップアクション、プレスアクション、リリースアクション
　コントローラーのスティック部分になります。

+ Oculus Touch (L or R) サムスティック
    + スティックの「<font color="red">**押し込み**</font>」を検知します。
    + PS4 コントローラーで例えるなら「L3, R3」に当たり、「スティックを押し込む」事で入力が入ります。[^1]

+ Oculus Touch (L or R) サムスティック タッチ
    + スティックの「<font color="red">**タッチ（触り）**</font>」を検知します。
    + 押し込まずタッチするだけで入力が入ります。[^2]
    + 中心の凹んでいる部分のみ反応します。

+ Oculus Touch (L or R) Thumb Up CapTouch
    + スティックの「<font color="red">**タッチ加減**</font>」を検知します。
    + 「タッチ」と「Up CapTouch」の違いはほぼ分からないですね。僅かに離れていても触れている判定になります。
    + 触れていたら０、検知範囲外なら１になります[^3]。「タッチ」と逆です。

+ Oculus Touch (L or R) サムスティック 上・下・左・右
    + 各４方向のスティックの「<font color="red">**倒し**</font>」を検知します。
    + 大体、軸取得の「0.7」前後で入力されている判定になるっぽいです。これの調整項目はあるのでしょうか？

+ Oculus Touch (L or R) サムスティック X・Y
    + 縦・横２軸のスティックの「<font color="red">**倒し加減**</font>」を検知します。
    + スティック軸の取得です。範囲は「-1.0 ~ +1.0」、正が``X``は右（→）、``Y``は上（↑）です。

上から見た図 ↓
![コントローラー トップ　サムスティック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/d386f727-e991-23be-cbec-ab068c4f5d61.png)
![入力一覧3 サムスティック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/dd1e5cbb-81f3-cb68-0fbb-9c51beb1224b.png)

[^1]: いわゆる、「カチッ♪」ですね。地味に好きなんですよね。あの音。
[^2]: 静電容量式を採用しているみたいです。確か、スマホのタッチ検知のシステムですよね？あまり詳しくないので、これ以上は言いません。でも、なぜ採用したのだろうか？
[^3]: 公式サイトでは「０～１」と表示されていたのですが、手元のUE4で試してみると、０と１しか出力されていませんでした。UE4のバージョンによる仕様変更でしょうか？

#### ・トリガーのタッチ、プレス、リリース、および指差しアクション
　コントローラーのトリガー部分になります。PS4コントローラーなら「R2, L2」に当たります。
　ちなみに、「UE4 Ver 4.72」では本来の「Oculus Touch (L or R) X, Y（押す・タッチ）」の部分が「Oculus Touch (L or R) トリガー X, Y（押す・タッチ）」になっています。つまり、「トリガー」を無駄に表示しています。

+ Oculus Touch (L or R) トリガー
    + トリガーの「<font color="red">**押し込み（押し）**</font>」を検知します。
    + 大体、軸取得の「0.8」前後で入力されている判定になるっぽいです。

+ Oculus Touch (L or R) トリガー 軸
    + トリガーの「<font color="red">**押し込み加減**</font>」を検知します。
    + トリガー軸の取得です。範囲は「1.0 ~ 0.0」です。

+ Oculus Touch (L or R) トリガー タッチ
    + トリガーの「<font color="red">**タッチ（触り）**</font>」を検知します。
    + 押し込まずタッチするだけで入力が入ります。
    + 中心の上側のみ反応します。

+ Oculus Touch (L or R) Pointing CapTouch
    + トリガーの「<font color="red">**タッチ加減**</font>」を検知します。
    + 「タッチ」と「Pointing CapTouch」の違いはほぼ分からないですね。僅かに離れていても触れている判定になります。
    + 触れていたら０、検知範囲外なら１になります。「タッチ」と逆です。

正面から見た図 ↓
![コントローラー フロント　トリガー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/1c3a249d-8d35-d762-99c8-b87fbe3349a4.png)
![入力一覧3 トリガー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/494508fc-d37f-2760-8521-7deabd6e8d9f.png)

#### ・グリップのプレスアクションとリリースアクション
　グリップはサイドのボタンの事です。名前は分からなくもないですね。

+ Oculus Touch (L or R) グリップ
    + グリップの「<font color="red">**押し込み（押し）**</font>」を検知します。
    + 大体、軸取得の「0.8」前後で入力されている判定になるっぽいです。

+ Oculus Touch (L or R) グリップ 軸
    + グリップの「<font color="red">**押し込み加減**</font>」を検知します。
    + グリップ軸の取得です。範囲は「1.0 ~ 0.0」です。

サイドから見た図 ↓
![コントローラー サイド　グリップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/83f92287-972a-a546-229f-c7154161124f.png)
![入力一覧3 グリップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/24dc320a-7f68-8169-c2bb-490e65612301.png)

#### ・X, Y, A, B, ホーム、システムボタンのプレスアクションとリリースアクション
　左が「X, Y, メニュー」右が「A, B, システム」になっています。サイト上では「ホーム・システム」なのに、UE4上では「メニュー・システム」になるのは止めて欲しいですね。統一して下さい。もしかして、バージョンのせい？

+ Oculus Touch (L, R) X, Y, A, B, メニュー, システム（押す）
    + ボタンの「<font color="red">**押し込み（押し）**</font>」を検知します。

+ Oculus Touch (L, R) X, Y, A, B
    + ボタンの「<font color="red">**タッチ（触れる）**</font>」を検知します。
    + システムとメニューはタッチ機能がありません。

![コントローラー トップ ボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/5e3e64bb-0f69-01c3-012f-ee23669415cd.png)
![入力一覧3 ボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/0e4be366-4d67-4db5-493c-c87ac7f8851f.png)

　念の為もう一度確認しておきますが、UE4では「トリガー」が余分に入ってしまっているので注意して下さい。流石にUE5では治ってると思いたいですが...。

### Oculus Remote
　すいません。これは分からないです。詳しい人教えて下さい。

### Oculus Hand
　恐らく、ハンドトラッキングの機能だと思います。詳細は各自で調べて下さい[^6]。現状使う予定は無いのですが、もし使うことがあるなら記述するかもしれません。

[^6]: Oculus Quest2にハンドトラッキング機能の存在に最近気付いたのは内緒です。

---

　以下のサイトからも参考にしました ↓

https://qiita.com/reisyu/items/6ee5a1f2e8c28525fb0c

https://developer.oculus.com/documentation/unreal/unreal-controller-input-mapping-reference/

# ゼロからコントローラーを動かす
　さて、入力関係の理解が終わったところで、前回作成した状態で実際にコントローラーを使ってみます。といっても、結構簡単に実装できます。

## ポーンにコンポーネントを設定
+ ポーンを親にしてブループリントを作成
+ 次にコンポーネントに「``Camera Component``・``Motion Controller Component``」を追加
    + ``Camera Component``の子に``Motion Controller Component``を２つ設定 ※左手・右手用です
    + UE4側で既にモーションコントロール用のコンポーネントがあるので使わせてもらいます。

![Motion Controller Component の設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/6adb1549-d826-d0cf-c0a1-395b7b6e0e0e.png)

## ``Motion Controller Component``の設定
+ 詳細 ＞ ビジュアリゼーション ＞ Display Device Model ＞ ON
+ 詳細 ＞ ビジュアリゼーション ＞ Display Model Source ＞ OculusHMD

![Motion Controller Component ビジュアリゼーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/7ae8296c-c16d-7d87-2a8c-7deebcc152d9.png)
　これら設定は「エンジン内のモデルを表示する？」と「どのモデル？」です。必須では無いのですが、とりあえず動いている事が分かるように設定しておきます。勿論、BP側で動的に変更できるので、「最初はコントローラーを表示しておいて一定時間後に消滅する」のような事をやってもいいかもしれません。

+ 詳細 ＞ モーションコントローラー ＞ Motion Source > ``Left`` か ``Right``

![Motion Controller Component モーションコントローラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/4c4b9582-2b62-6b02-47b7-be200a2af340.png)
　この設定は「このコンポーネントはどのコントローラーを指定するか」になるため必ず設定が必要です。出ないと、両方とも左手（デフォルト）の動きを再現してしまいます。忘れないようにして下さい。

## ``Begin Play``での初期化
　最後に、Set Tracking Origin関数を呼び出して、引数はFloor Levelを設定して下さい。Oculus Quest2は「6Dof」なので「Floor level」になります。
　「6DoF」って何ぞや？という話なのですが、簡単に言うと、「頭の``回転``（3DoF）+ 頭の``移動``（3DoF）= 6DoF」ということです。詳細は下記サイトを覗いて下さい。~~拡大まで付けば9Dof~~

https://www.pupuru.com/blog/vr/vr-dof

![Motion Controller Component SetTrackingOrigin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/176f4f50-6db3-eff1-f488-73e99f22c1f6.png)
※ 上図のノードコメントに「6DX」と書いてますが間違えてます。「6DoF」です。

## コントローラーが動いたよ！やったね！
　単純にコントローラーを動かすなら上記項目を設定するだけで完了です。相変わらず手軽に出来るのでUE4君は凄いですね...。
![モーションコントローラー テスト.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/4f8a48d0-6151-09fe-3f6f-0ff4f343359e.gif)
※ 背景はアセットを使用しています（若干見づらくなったのは気のせいです）

# VRをどう料理するか？
　私自身、VRゲームを作ったことは全く無いので、手探りで作成していきます。
　今回は、敵UFOを打ち落とす360°シューティングにしようと思います。「自機は中心で、全方向からやってくる敵を打ち落としていく」というシンプルイズベストなものです。自機に敵が当たって体力が無くなればゲームオーバーになり、ゲームオーバーになるまで永遠に続きます。
　操作は立つか、回転する椅子に座ってプレイします。つまり、自機を中心にして敵が動いてくるので、移動する必要はありません。回転（振り向き）だけに集中出来て、「VR酔い」はほぼ無いはずです。
　ただでさえ普通のゲーム企画を考えるのは大変なのに、VRゲームの企画なんぞ無理なので、サンプルVRゲーム的なものになるのは許して下さい。内容自体は極々シンプルなのでVRゲーム開発か？と言われると違う気もするのですが、気にしてはいけません。

![サンプルゲーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540257/dae64d7e-1a83-78a2-e8a2-2c437635e55f.png)

## VRゲームの難しいと思える所
+ 「VR」が必要と思える事（VRだと楽しいと思えるもの）
+ 出来る限りVR酔いを回避する事（実際の動きと違う事をするとかなり酔います）
+ VRでのUI配置・表示（調べてみると非常に難しいみたいですね...）

他にもあると思いますが、現状思ったものを挙げています。こう考えると、面白いVRゲームを作るとなると非常に難しい事になりますね...。う～ん...

# 次回へ
　次回はVRでのUIとゲーム作成を取り扱おうと思います。下記の参考サイトでやり方はネタバレしてます。

# 参考サイト

https://developer.oculus.com/documentation/unreal/unreal-controller-input-mapping-reference/

https://qiita.com/reisyu/items/6ee5a1f2e8c28525fb0c

https://www.tachfirst.com/2021/06/14

https://www.slideshare.net/historia_Inc/vrui-78798570

https://docs.unrealengine.com/4.26/ja/InteractiveExperiences/UMG/HowTo/InWorldWidgetInteraction/

https://note.com/fujisunflower/n/n0a7f28f7f4b1

https://pafuhana1213.hatenablog.com/entry/2016/01/06/232858

https://qiita.com/reisyu/items/6ee5a1f2e8c28525fb0c

https://developer.oculus.com/documentation/unreal/unreal-quick-start-guide-quest/?locale=ja_JP

https://developer.oculus.com/documentation/unreal/unreal-controller-input-mapping-reference/

https://shiratori1221.hatenablog.com/entry/2020/06/19/001201

https://unlimited-games.hatenablog.com/entry/2020/12/11/085533

https://www.pupuru.com/blog/vr/vr-dof

https://www.unrealengine.com/marketplace/ja/item/b3024ba800764f37907f3680dde8aa9a