
Quest3MR開発入門
この記事はjig.jp Advent Calendar 2023の12月14日(木)の記事です。
こんにちは、jig.jp 社員の 渡邊 です。
先日Quest3が発売されました。Quest2から画質、装着感などが改良されかなり遊びやすくなったと感じます。
中でもAR,MR機能は目玉の一つです。それらを活用した Figmin XRというアプリがこちら。
🎉With #Quest3 the real world is your playground! 🎉#MixedReality #AugmentedReality #FigminXR #MetaQuest3 pic.twitter.com/yRd34OJXQP
— Figmin XR (@FigminXR) October 4, 2023
事前にQuest側でスキャンを行い、それに合わせて物理演算、射影、カリングなどを行ってくれる面白いアプリです。
ARを超えて本格的にMR(Mixed Reality)の域に入ってきていると感じさせます。
さて、今回はQuest3でUnityを使ったMR開発を行うまでの手順をまとめました。
環境
Windows 10
Unity: 2022.3.11f1
Quest ver: 57.0.0.279.669.521490460
*Oculus Integrationパッケージを使用するにはUnity 2021.3以降のバージョンが必要です。
導入
開発者モードをON
スマートフォンからMetaQuestアプリにログインし、Quest3と接続します。
スマホからデバイスを選択、「ヘッドセットの設定」内にある開発者モードをONにします。

adb command セットアップ
https://developer.oculus.com/downloads/package/oculus-adb-drivers
より、ADB Driversをダウンロードします。
zipファイルを解凍し、android_winusb.infを右クリック→インストールします。
Quest3をPCに接続して、PCでターミナルを開き、次のコマンドから接続されているか確認します。
adb devices
Meta XR All-in-One SDKの導入
下記URLにアクセスし、Add My Assetsをクリックしてライブラリに追加します。
https://assetstore.unity.com/packages/tools/integration/meta-xr-all-in-one-sdk-269657
新規プロジェクトを作成してUnityを開きます。
上部メニューの ウィンドウ>パッケージマネージャを選びます。
左上のパッケージ選択からマイアセットを選択、Meta XR All-in-One SDKがあるはずなのでダウンロード、インポートします。(画像の名前が古いものになっていますが、Meta XR All-in-One SDK をインポートしてください)

Oculus Integration インストール中のダイアログは下記のように選択します。
Yes, just for these files
Send usage statistics(どちらでも)
Show Assets(Recommended)
Clean Up(Recommended)
Clean Up Package
Restart
Upgrade
Restart
自動的に再起動します。


Meta XR All-in-One SDKの設定
上部メニューの 編集>プロジェクト設定を選びます。
プロジェクト設定の Oculus を開きます。
Androidアイコンタブに移動、Fix All, Apply Allのボタンを押します。
一度押しても残ることがありますが、何度かFix All を押せば消えます。

MR作成
ARカメラ作成
プロジェクト内のAssets > Oculus > VR > Prefabsを選びます。
OVRCameraRigとOVRSceneManagerをヒエラルキーに追加します。(ドラック&ドロップ)

ヒエラルキー内の OVRCameraRig をクリックしてインスペクターを表示し、上から順に設定を変えていきます。
OVR Manager(スクリプト)>Target Devices をQuest3のみに変更します。

OVR Manager(スクリプト)>Quest Featuresを選びます。
Scene Supportを必須に変更します。
Passthrough Supportを必須に変更します。
(Anchor Supportは自動で有効になります)

Mixed Reality Capture▶️Enable MixedRealityCaptureにチェックします。
Enable Passthroughにチェックします。

コンポーネントを追加 > OVR Passthrough Layer を追加します。

追加した OVR Passthrough Layer 内の Placement を Underlay に変更します。

OVRCameraRig の設定はこれで終わりです。
半透明マテリアル作成
メッシュ確認のため、MR上の当たり判定可視化の用の半透明マテリアルを作成します。
プロジェクトの Assets内にMyAssetsフォルダを追加します。

MyAssetsで右クリック>作成>マテリアルを選びます。
名前は「translucent」に変更します。

translucentを開きます。
Rendering ModeをFadeに変更します。
アルベドをクリックしてAの値を20に、それ以外は適当に好きな色を選択します。

MRメッシュ取得
ヒエラルキーに元からあったカメラは不要なので削除します。
ヒエラルキー内で右クリックして「空のオブジェクトを生成」を2回実行します。
名前は「EmptyScneAnchor」と「GlobalMesh」に変更します。

EmptyScneAnchorのインスペクターを開きます。
コンポーネントを追加からOVR Scene Anchorを追加します。

GlobalMeshのインスペクターを開くします。
コンポーネントを追加から次のものを追加します。
OVR Scene Anchor
Mesh Filter
OVR Scene Volume Mesh Filter
Mesh Collider
Mesh Renderer
追加後、Mesh Renderer の Materials を開き、先ほど作成した translucent をドラック&ドロップで適用します。

EmptyScneAnchor と GlobalMesh をMyAssets内にドラック&ドロップしてプレハブ化します。
その後ヒエラルキー内のEmptyScneAnchorとGlobalMeshは消します。

OVRSceneManager のインスペクターを表示します。
Prefab Overrides を展開して右下の+をクリックします。
GLOBAL MESHに切り替えてプレハブにGlobalMeshをドラック&ドロップします。
Plane PrefabとVolume PrefabにEmptyScneAnchorをドラック&ドロップします。

ビルド
ビルド設定
上部メニューの Oculus > ツール > Create store-compatible AndroidManifest.xml をクリックします。
ダイアログの Replace を選択します。

上部メニューの ファイル>ビルド設定を選びます。
Androidを選択し、ターゲットの切り替えを押します。

ビルド実行前に
上部メニューの 編集 > プロジェクト設定 > Oculusを選び、
Androidアイコンタブに移動し、Fix All, Apply All を押します。
ビルド
上部メニューの ファイル>ビルド設定からビルドを実行します。
適当な名前で保存します。(ここではsample.apk)
ターミナルを開いてapkファイルを保存したところまで移動しadb install -r sample.apkを実行、apkをインストールします。
※うまくいかない場合は adb devices 等で接続を確認してみて下さい
Questをかぶり、「アプリライブラリ」から アプリを検索(上部) > 右上のメニューから[提供元不明]を選択
ここにインストールされている事が確認できると思います。

動作確認
Quest3上で実行すると動いている事が確認できると思います!
(ちょっとわかりにくいけど椅子とクッションのメッシュが取得できています)

続いてはコントローラーに関する設定です。
コントローラー
ランタイムコントローラーの設定
ランタイムコントローラーとは、AR(VR)内でもコントローラーの動作が反映される技術のことです。

プロジェクトの Assets > Oculus > VR > Prefabs を開いてOVRRuntimeControllerPrefabを見つけます。
ヒエラルキー内の OVRCameraRig > TrackingSpace > LeftHandAnchor を展開して LeftControllerAnchor を見つけます。
LeftControllerAnchor の子コンポーネントとして OVRRuntimeControllerPrefab を配置します。(ドラック&ドロップ)

配置したOVRRuntimeControllerPrefabのインスペクターを開き、コントローラーの値をL Touchに変更します。

RightControllerAnchor も同様に OVRRuntimeControllerPrefab を配置、インスペクターを開いて、コントローラーの値をR Touchに変更します。

ここまででビルドしてみると、ランタイムコントローラーが反映されていることがわかると思います。
コントローラーの入力受付
次はスクリプト内でコントローラーの入力を検知する方法について説明します。
ヒエラルキー内で右クリック>空のオブジェクトを生成を選び、
名前は「ControllerScript」に変更します。
ヒエラルキー内で右クリック>3Dオブジェクト>スフィアを選び、
名前は「ball」に変更します。

ballのインスペクタを開き、スケールを0.1に変更します。
コンポーネントを追加 からRigidbodyを追加します。


ballをヒエラルキー内からMyAssets内にドラック&ドロップしてプレハブ化します。

プレハブを生成できたらヒエラルキー内のballは削除します。
MyAssets内で右クリック > 作成 > C#スクリプトを選びます。
適当な名前をつける、ここでは「SampleScript」に変更します。

作成したスクリプトをダブルクリックして編集を選び、
下記のように書き換えます
using UnityEngine;
public class SampleScript : MonoBehaviour
{
// ここで指定したオブジェクトの位置や角度を基準にする
[SerializeField] private GameObject controlPoint;
// 入力ボタンフィールをを作成できる
[SerializeField] private OVRInput.RawButton inputBtn;
// 生成するオブジェクト
[SerializeField] private GameObject ball;
private void Update()
{
// 指定したボタンが押されたら
if (OVRInput.GetDown(inputBtn))
{
// ballをcontrolPointの位置を合わせて生成する
Instantiate(ball, controlPoint.transform.position, Quaternion.identity);
}
}
}
ControllerScriptのインスペクターを開き、SampleScriptをドラック&ドロップしてコンポーネントを追加します。
Control PointにOVRRuntimeControllerPrefab、InputBtnにXを選択、BallにMyAssets内のballをドラック&ドロップして設定します。

確認
ビルドして実行します。
左のコントローラーのXボタンを押すとボールが出るようになっていると思います。
さらに、生成されたボールがメッシュに当たって転がる様子が確認できると思います!

これらの技術を活用して思い描いた世界を作ってみましょう!
※弊社は業務でUnityを書いているわけではありません
おまけ:カリングしたい!
このままだとメッシュの裏に行った場合に半透明で見えてしまいます。
実際にある物体の裏に隠れている場合は見えない方が良いですね。
カリング
MyAssets 内で 作成>シェーダー>標準サーフェスシェーダーを選びます。
名前は「Cutout」に変更する。

Cutoutをダブルクリックで編集する。
中身を下記のように書き換えます。
Shader "Custom/Cutout" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
}
SubShader {
Pass{
ColorMask 0
}
}
}
translucentのインスペクターを開き、Cutoutをドラック&ドロップで適用します。

translucentのインスペクター内にあるレンダーキューの値を1999に変更します。

ビルドして起動すると裏に隠れていることを確認できます。

参考文献
開発とテスト用にデバイスを有効にする
チュートリアル - Meta QuestヘッドセットでのHello VR
Unity設定を構成する
OVRCameraRigを使用してカメラRigを追加する
パススルースタートガイド
Scene Mesh
コントローラーのマッピング
ランタイムコントローラー