こわくない Meta Quest 開発

## アドカレの告知

:::note info
この記事はデジクリ Advent Calender 2023 11日目の記事です。
デジクリは芝浦工業大学の創作サークルです。
デジクリについて、詳しくは[こちらのサイト]()をご覧ください。
10 日目の記事は 19th さばみそ さんの「[Astro と Panda CSS による静的サイト制作のすゝめ](https://meiryo7743.net/ja/blog/building-a-static-website-with-astro-and-panda-css/)」です。
:::

## はじめに

こんにちは！芝浦工業大学の学生で、きたぴーと申します！

先日、JPHACKS という全国規模のハッカソンにチームで出場して、「[スマートホームメイド](https://jphacks.com/information/award-finalists2023/)」という MR (複合現実) の作品を提案しました。そこで使った当時発売されたてほやほやの Meta Quest 3 を使った開発をしたわけですが、**めちゃめちゃ情報が少ない...。** 日本語の情報が全然なくて公式ドキュメントを読むのも一苦労でした。

そこで！今回 JPHACKS で培った Meta Quest での MR 開発の知識を **Meta Quest 開発未経験の方にもわかりやすい形** で概観できるような記事を書きたいと思って今回筆を取りました。こういった形で技術記事を書くのは今回が初めてで拙い文章ではありますが、ぜひ最後までお付き合いいただいて、いいねやコメントを頂けますととても励みになります！

![インタラクションの様子](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/e72872b5-54b6-cc52-8b5f-37912cf07360.gif)

:::note warn
注意事項: この記事では Unity での Meta XR Interaction SDK を使った手のインタラクションに焦点を当てています。ほかの内容については扱っていません。
:::

## Meta XR SDK ことはじめ

### インストール

Asset Store の [Meta アカウント](https://assetstore.unity.com/publishers/25353) に飛べば、SDK が一式そろっています。Meta XR All-in-One SDK を入れたらすべての機能が使えるようになりますが、GitHub などを使おうと考えている場合、**3 GB** とかいう結構デカめのリポジトリが出来上がるので、そういった場合には必要最小限の SDK をインストールすることをお勧めします。(公式サイトの UnityPackage からインストールする方法は Deprecated らしいです。)

![Meta の Asset Store](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/ca166b12-98cc-b9c5-d037-7f888ffa478f.png)


### 事前準備

この Interaction SDK を使う前に、Core SDK の基本的なプレハブを用意する必要があります。でも、手順はめちゃめちゃ簡単です。V59 の SDK からは Building Blocks がかなり進化しているようなので煩雑な Prefab 操作は不要になっています。

ツールバーの `Oculus` > `Building Blocks` からウインドウを表示します。

![ツールバーの画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/167b7a9e-daeb-d7f9-9613-0fc8fd0fc0f6.png)

そうすると、VR もしくは MR で使える機能が並ぶので、欲しい機能をクリックするだけで勝手に Scene に配置してくれます。下のスクショではすでに Camera Rig と Passthrough を選択済みです。右の Hierarchy に [BuildingBlock] という接頭語のついた GameObject が確認できると思います。

![Building Blocks のスクショ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/4d35c492-2c5c-b165-4da7-8a44bfd52ba0.png)

この中で今回使った機能は以下の通りです。それぞれ詳細説明は後ほど行いますが、この中で下から3つの `.*Item` がこの記事の本題です。

- Camera Rig
- Passthrough
- Hand Tracking
- Synthetic Hands
- **Pointable Item**
- **Pokeable Item**
- **Grabbable Item**

## いざ、Interaction SDK

[公式ドキュメント](https://developer.oculus.com/documentation/unity/unity-package-manager) より、Interaction SDK の役割に関する説明を抜粋します。

> Interaction SDK adds interactions like ray, poke, locomotion, grab for controllers, hands, and controllers as hands.

ray、poke、locomotion、grab っていう動作を手やコントローラで使えるようにします。みたいなことが書いてありますね。それぞれ、指で指す、つつく、移動する、掴む、という動作と対応します。順を追ってみてみましょう。

:::note info
この記事は MR に使える Interaction の機能を紹介する目的で執筆しているので、VR での使用がメインな locomotion については扱いません。
:::

### Ray 指す

ちょっと遠めのオブジェクトに対してインタラクションしたいとき使うのが Ray です。親指と人差し指を開いた状態でカーソルを合わせて、閉じるとクリックするようなイメージです。

![Ray の Example](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/1dc35216-95f4-02d5-7b74-aa35e93b6ede.gif)

### Poke つつく

ボタンを押すようなインタラクションを Poke といいます。ほかにも Interaction SDK の Example を眺めてみると、ハンドシミュレータに出てきそうなボタンも Poke で実装されています。

![Poke のハンシュミ Example](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/85d1dc02-be66-c9b0-823c-f9879cf72f88.gif)

### Grab 掴む

手元にあるオブジェクトをつかんで移動させたいときに使うのが Grab です。つかむポーズも指定できるみたいです。以下の GIF だと、鍵をつかむのは2本の指ですが、松明をつかむときは手のひらでつかんでいます。(この Custom Pose の機能、今回調べてみて知ったので未検証です。)

![Grab の Example](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/bf27b64e-88e7-299f-5170-9f868d2dc0c1.gif)

:::note info
これら 3 つのインタラクションのコンポーネントは全部 IInteractable を継承したクラスで内部的に実装されています。Poke で実装されている、という言い回しをしたのはこのためです。
:::

## 意外と大事なやつら

Meta Quest でできるインタラクションはだいたいこんな感じです。あとは先ほど Building Blocks の時に飛ばした残りの機能について軽く見ていきます。

### Camera Rig

プレイヤーの Prefab です。Meta Quest の開発では必須になる Prefab で、この子オブジェクトに色々 Prefab とか Component とか必要に応じてアタッチします。Bulding Blocks が自動的に設定しているのはこのあたりです。

<details> <summary>参考までに...</summary>

ハッカソンの開発で私がよくいじったのは `TrackingSpace` > `Left(Right)HandAnchor` と、`[BuildingBlock] Interaction` > `[SBB] Hand Tracking` あたりでした。ここら辺をいじると Interactable なオブジェクトにインタラクションができるようになります。詳しくは [公式ドキュメント](https://developer.oculus.com/documentation/unity/unity-isdk-getting-started/) を参照してください。

</details>

![Camera Rig の Hierarchy](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/12d2770a-a803-53fa-97ec-18f2e80cce3e.png)

### Passthrough, Hand Tracking

Camera Rig に対してそれぞれ、MR 用のパススルー設定、ハンド度ラッキング用の Prefab を追加するのがこれらの Building Block です。

<details> <summary>余談ですが...</summary>

V57 時点だと私の環境ではうまく Building Block が動作せず、公式ドキュメントの設定を Scene ごとにやっていました。めっちゃ面倒でした...。

</details>

### Synthetic Hands

手の輪郭を表示する機能です。これ、実は UX 的に割と重要なんです。なぜかというと、基本、自分の指は**オブジェクトを貫通します**。そうすると Poke 判定の範囲がわからなくて戸惑います。Grab の時にはそもそも自分の手がどういうポーズで認識されているのかこっちはわかりません。このような理由から、Synthetic Hands は重要です。

この GIF は左が Poke を実装した Plane と実装していない Plane の比較です。上から見ると、一目瞭然だと思います。

![Synthetic Hands の比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/09b32ee1-91eb-32ed-80d5-2215268900f5.gif)

### Interactable Unity Event Wrapper

Interactable なオブジェクトに対するコールバックは、`InteractableUnityEventWrapper` で設定します。今回の冒頭のデモで使用したのは Select で、押されたときを表します。

SDK の Example にて、Meta Quest の木魚の音みたいな、インタラクション時の「ポクっ」という音が Select() のコールバックとして AudioSource.Play() が指定されていました。

![コールバックの設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2657577/ca9dc134-4b49-c546-768f-0cc5b96de9f2.png)

## まとめ

Meta Quest で手のインタラクションは3つに大別できる！

- Ray 指をさす
- Poke つつく
- Grab 掴む

## 最後に

メタクエ完璧に理解した！くらいの勢いでしたが、いざ技術記事としてまとめてみると自分の無知さを自覚しますね...。これから MR を使った面白い表現を研究していきたいと考えているので、メタクエの C# 内部実装についても知見を深めていきたいと思います。いいねがついて好評そうだったら今回扱いきれなかった`Spatial Anchor` (空間アンカー) など年末年始にちまちま書いてみようかなと思います。最後までお付き合いいただきありがとうございました🙇‍♂️

## 執筆環境

- Unity 2022.3.12f1 <DX11>
- Meta XR Core SDK, Interaction SDK OVR v59.0.0
- Windows 11 Education 22H2 22621.2715