Oculus Quest 2 のパススルー機能を有効化して、ARアプリを作成する

## 環境
- Meta Quest 2
- Windows10
- Unity 2021.3.13f

## やること
Meta Quest 2のパススルー機能を有効化して、簡単なARアプリを作成します。
もしMeta Quesst Proを持っていれば、カラーパススルーを使うこともできるはずです。

## 参考サイト
https://github.com/oculus-samples/Unity-TheWorldBeyond
https://developer.oculus.com/documentation/unity/unity-overview/
https://framesynthesis.jp/tech/unity/oculusquest/

## 手順
### 環境構築
https://developer.oculus.com/documentation/unity/unity-gs-overview/
を見ながら、Unityの環境構築とMeta Quest 2の開発者モードの有効化を行います。
Unity側の設定は基本的に、
- Oculus統合のインポート
- ビルドプラットフォームのAndroidへの変更
と覚えておけば問題ないと思う。
Meta Quest 2の開発者モードの有効化には、スマートフォンが必要で、以下の手順で行います。
**メニュー -> デバイス-> 開発者モード-> トグルオン**

### カメラ設定
OVRManagerというスクリプトを使うのだが、Oculus統合の中に入っている「OVRCameraRig」をHierarchyにドロップするのが一番はやいです。
VRアプリの開発だと「OVRPlayerController」を使うのだが、ARの場合はコントローラによる移動は発生しないので、これは使わないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/dd53abcb-9ebc-866c-2b3d-f1b3a72089a8.png)

OVRCameraRigの中には、OVR Managerというスクリプトが入っているのですが、これを使ってパススルー機能を有効にすることになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/ad3c698e-bcaa-11ad-c51b-8dafe35eef2e.png)

1. Quest Features のGeneralの中から、Passthrough Capabilityを有効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/287069ad-1f53-37ab-9993-480278e17a46.png)

1. 同様Experimentalの中から、Experimental Features Enableを有効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/3206935a-e0fa-2aca-1014-29bb5e079937.png)

1. Mixed Reality Capture以下の設定はenableMixedReality、Enable Passthroughを有効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/40d12ecf-e37b-3612-95fd-41f756a610a6.png)

1. この後、OVRCameraRigに更に「OVR Passthrough Layer」をセットアップする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/a4ae9201-fa29-f9cb-631d-9580a4a98ad3.png)

UnderlayとOverlayの違いは、Viveのページだけどもこれが参考になりました。
https://forum.htc.com/topic/12743-updatewave-450-demonstration-on-how-to-use-wave-passthrough-underlayoverlay-apis/

1. このままだとPassthroughの画面よりUnityのSkyboxが優先して表示されてしまい、Passthroughが有効になっているように見えないと思うので、Lighting設定からSkyboxを消します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/1e1d145a-dd5c-7e15-b221-f7eb31225932.png)

ここまででシーンに適当なオブジェクトを置きつつ、Build and Runしてみれば、Quest2上でPassthroughが表示され、オブジェクトも表示される様子が確認できるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/6a22e10a-af8f-9e13-50f9-22f915927c50.png)

Passthroughの画面はUnityのスタートボタンからだともちろん表示されないので、ちゃんとBuild and Runしてください。

### GrabberとGrabbable
物を持てるようにするために、GrabberとGrabbableの設定をします。
とりあえず、コントローラーの位置にコントローラーを表示すべく、以下のように設定してください。
OVRControllerPrefabをそれぞれのControllerAnchorの下に置くだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/b85523e9-d2d9-2bc2-cbc2-9a7ad76d7cdd.png)

そうしたら、それより上位のLeftHandAnchorにRigidbodyとOVRGrabberを設定しますが、RigidbodyのUse Gravityを外すのを忘れないでください。そうしないとコントローラーは開始早々下に落下して消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/11a64173-627c-cc9b-15a2-a0791d1c9436.png)

Grab Volumesには、OVRControllerPrefabにアタッチした球体コライダーを設定しました。

持たれる側のオブジェクトには
1. OVRGrabbable
1. Rigidbody
1. Collider

の3点セットがあれば大丈夫です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/7c6913e3-b6f3-e2a6-00fb-5cc3b74a9301.png)

この時点で、起動するとパススルーで背景が表示され、コントローラーの位置にはバーチャル上でもコントローラーが表示され、物体を持つことができるARアプリになってると思います。

### 天井や壁の位置にバーチャル上で何か表示したり
**ここから先をやる場合、OVR ManagerのAnchor SupportがEnableになってるか確認してください。**
現実の部屋の壁や天井の位置に対してAR空間上で何か表示させたり、衝突判定を行いたい場合、SceneAPIというものを使います。
というのも、Oculus Quest 2は別に壁の位置なんかを自動認識したりはしないので、あらかじめQuestの設定から、部屋を認識するための設定を行うのです。
その設定をSceneAPI経由で呼び出して、Unityアプリ上から操作することができます。

Quest2の設定から、「試験中」->「ルーム設定」で部屋の壁をなぞるようにすることで、SceneAPIで使う壁や天井、床、家具などの位置の情報がQuest2本体に登録されます。
これはQuest2が開発者モードになっていなければなりません。

そしてSceneAPIは「OVRSceneManager」というPrefabを通して扱っていきます。
とりあえず「OVRSceneManager」をシーン上にドロップすると、OVR Scene ManagerのPlanePrefabとVolumePrefabが空白になってると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/b1afcd45-e267-d584-cbc7-e189a739bc55.png)

#### PlanePrefabの作り方
GameObjectにOVR Scene Anchorと、Furniture Spawnerをアタッチします。
Furniture Spawnerでは、SceneAPIで取得した壁や天井などの情報に、どのプレファブを召喚するか設定します。
画像では、天井に対して、Waterというプレファブを召喚しろという設定になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/5cb053d8-10d9-ef64-a11a-9872f5aff9c8.png)

#### SpawnablePrefabの作り方
といっても天井はすべての環境で同じなわけではありませんから、SpawnableObjectには天井や壁の大きさに合わせて自動でリサイズする機構が必要です。
これがSimpleResizableで、WaterPrefabは実際に以下のようになってます。
これはただSimple Resizableをアタッチしただけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491627/a14e2fd1-8094-dff9-ce55-4219a47a8707.png)

このようにSpawnablePrefabにコライダーなども設定しておけば、現実空間上の壁や家具の位置に衝突判定を発生させることもできます。
これ以上の応用は、
https://github.com/oculus-samples/Unity-TheWorldBeyond
を読み解くのが一番いいかなと思います。


## 終わりに
質問やご指摘などがあれば是非。
それでは