MRTKを使ったMeta Quest 3でビデオシースルーで周りの風景がみえるMRアプリを作ってみましょう。
開発環境
Meta Quest 3アプリをMRTKで開発する場合の2024/01現在の環境は次のような環境になります。
- Unity 2022.3.18f1
- Mixed Reality Feature Tool 1.0.2209.0
- MRTK3
- MRTK Graphics Tools 0.6.7
- MRTK Core Definitions 3.0.1
- MRTK Input 3.0.0
- MRTK Spatial Manipulation 3.0.0
- MRTK Standard Assets 3.0.0
- MRTK UX Components 3.1.0
- MRTK UX Core Scripts 3.1.0
- Mixed Reality OpenXR Plugin 1.9.0
実装
- Unityで空のプロジェクトを新規作成
- Mixed Reality Feature ToolでMRTK3をインストール
- MRTK3の設定
- シーンの設定
- サンプルオブジェクトの配置
- ハンドメニューの追加
Unityで空のプロジェクトを新規作成
新規作成
Unity Hubを起動したら、[Projects]メニューから[New Project]をクリックして新規プロジェクトを作成します。
テンプレートとUnity Editorバージョンの指定
テンプレートとしては「3D」を選択し、プロジェクト名には「MetaSeeThroughWorld」とします。もちろんプロジェクト名は任意につけることができるので他の名前でもOKです。
もし、複数のUnity Editorをインストールしている場合は、利用するUnity Editorのバージョンが想定しているバージョンか確認して必要に応じてバージョンを選択しなおしてください。
Mixed Reality Feature ToolでMRTK3をインストール
ダウンロード
ダウンロードサイトから「MixedRealityFeatureTool.exe」をダウンロードします。インストーラーではなく実行ファイルそのもののダウンロードとなります。
www.microsoft.com
Mixed Reality Feature ToolでUnityプロジェクトフォルダを指定
Mixed Reality Feature Toolを起動したら、MRTK3を配置するUnityプロジェクトフォルダを指定して、[Discover Features]ボタンをクリックします。
導入機能の選択
今回導入する機能を次の機能になります。
- MRTK3
- MRTK Graphics Tools 0.6.7
- MRTK Core Definitions 3.0.1
- MRTK Input 3.0.0
- MRTK Spatial Manipulation 3.0.0
- MRTK Standard Assets 3.0.0
- MRTK UX Components 3.1.0
- MRTK UX Core Scripts 3.1.0
- Platform Support
- Mixed Reality OpenXR Plugin 1.9.0
導入する機能を選択して、[Get Features]をクリックしてUnityプロジェクトにMRTK3に含まれている機能から使用する機能を追加します。
選択した機能を確認したら[Import]ボタンで導入します。
MRTK3の設定
Unity Editor 起動
MRTK3導入後の初回起動時に、MRTK3が使用している「Unityの新しいInput System」を使用しているため、切り替え確認ダイアログが表示されるので、[YES]をクリックして先に進みます。
シーンの設定
それでは、「シーン」を設定してMRTK3が利用できるように設定します。
シーンのカメラ削除
シーンに初期設定されている「Main Camera」ではなく、MRTK3のカメラを使うので「Main Camera」は削除します。
[Hierarchy]タブの「Main Camera」を右クリックしてメニューから[Delete]を選択して削除します。
MRTK XR Rigの追加
[Project]タブの[Packages]-[MRTK Input]-[Assets]-[Prefabs]から「MRTK XR Rig」を[Hierarchy]タブへドラッグ&ドロップして追加します。
MRTK XR Rigの設定
「MRTK XR Rig」の初期設定値では、[Camera Y Offset]がY方向「1.6」mとなっています。
この「MRTK XR Rig」がアプリ上のカメラであり、Meta Quest 3を被った時の目の位置と目線の方向を表しますので、このオフセット値を0に設定します。また、[Position Y]も「0」、[Tracking Origin Mode]も「Device」とします。
- Position:0, 0, 0
- Tracking Origin Mode:Device
- Camera Y Offset:0
Input Simulatorの追加
Unity Editor上でデバッグするときに、Meta Quest 3の入力をキーボードでシミュレートするための機能「Input Simulator」を追加します。
[Project]タブの[Packages]-[MRTK Input]-[Simulation]-[Prefabs]から「MRTKInputSimulator」を[Hierarchy]タブへドラッグ&ドロップして追加します。
これでUnity Editor上でPlay Modeにすると[Shift]キーで左手、[Space]キーで右手の操作がシミュレートできるようになります。
learn.microsoft.com
サンプルオブジェクトの配置
共通設定が完了したらMRアプリのHello Worldともいえる空中に浮かんだCubeを表示するアプリを作成します。
Cubeの追加
[Hierarchy]タブを右クリックして、[3D Object]-[Cube]メニューをクリックしてCubeを追加します。
Cubeの位置と大きさを調整
初期位置ではカメラと重なってしまうので、[Hierarchy]タブで「Cube」を選択して、その[Inspector]タブで[Position]を(0, 0, 2)=2m先の位置、[Rotation]を(30, 30, 0)、[Scale]を(0.5, 0.5, 0.5)にして配置します。
Cubeへの物理演算追加
Cubeの[Inspector]タブで[Add Component]ボタンをクリックして、[Physics]-[Rigidbody]を選択して、Cubeに物理演算が適用されるように設定します。
また、初期状態では重力が聞いている状態なのでアプリを動かした途端にCubeが自由落下で下に落ちてしまうので、[Use Gravity]のチェックを外します。
Cubeへの操作追加
Cubeの[Inspector]タブで[Add Component]ボタンをクリックして、[MRTK]-[Special Manipulation]-[Object Manipulator]を選択して、CubeにMRTKによる操作が適用されるように設定します。
learn.microsoft.com
ハンドメニューの追加
MRTKにはHoloLens 2などで実装されているハンドメニューを実現する部品があります。
[Project]タブの[Packages]-[MRTK UX Components]-[HandMenu]から「HandMenuBase」を[Hierarchy]タブへドラッグ&ドロップして追加します。
[TMP Importer]ダイアログが表示された場合は、[Import TMP Essentials]ボタンだけクリックして、TextMeshProのリソースのみをインポートしてください。
初期状態の確認
「HandMenuBase」を[Hierarchy]タブに配置出来たら、[Inspector]タブ[Position Z]を0.5に変更してカメラの前に配置して、Playボタンで実行してみましょう。
youtu.be
このように縦に4つのボタンが表示され、左手または右手の操作をシミュレートしてあげればメニューを選択する動きが再現できます。
なお、初期状態では、顔から少し離れた位置で手をかなり平らな状態で視線に対して75度以上の角度でカメラの前(視線の前)に持ってくるような動きが必要です。
一番下のボタンに「終了」を割り当てる
[Hierarchy]タブの「HandMenuBase」の中をクリックしていって、「Action Button (4)」の[Frontplate]-[AnimatedContent]-[Icon]-[UIButtonFontIcon]を選択します。
[Inspector]タブで「Front Icon Selector」コンポーネントを探して、その中から「アプリケーションの終了」を意味するアイコンを選択します。
アプリケーション終了の実装
C#コード
[Project]タブの[Assets]を右クリックして[Create]-[Folder]メニューを選択して、[Assets]の中に新しいフォルダを作成します。フォルダ名は「Scripts」とします。
[Scripts]を右クリックして[Create]-[C# Script]メニューを選択して、C#のコードを記入するファイルを作成します。ファイル名は「Menu」とします。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Menu : MonoBehaviour { public void ApplicationExit() { Application.Quit(); } }
C#コードをHandMenuBaseに追加
[Hierarchy]タブの「HandMenuBase」を選択し、[Inspector]タブの[Add Component]ボタンで[Scripts]-[Menu]を選択します。
Action ButtonのClickイベントに「ApplicationExit」メソッドを割り当て
[Hierarchy]タブの「HandMenuBase」の中をクリックしていって、「Action Button (4)」を選択します。
[Inspector]タブで[Pressable Button]の[On Clicked()」で、「HandMenuBase」を選択してから、「No Function」と表示されているドロップダウンリストをクリックして[Menu]-[ApplicationExit()]を選択します。
Unity EditorのPlay Modeでハンドメニューを表示する
[Shift]を押して左手シミュレートを表示したら[P]キーを押ししてから[F]キーを押して手のひらを返すとハンドメニューが表示できます。
Meta Quest 3 固有機能の実装
- Meta Quest 3用必要アセットのインポート
- ターゲットプラットフォーム指定
- Player設定
- Quality設定
- MRTKプロファイル作成
- XR Plugin Management (Open XR) の設定
- ビデオシースルー設定
- 壁や床を検出する
Meta Quest 3用必要アセットのインポート
アセット追加
Meta Quest 3に合わせたアプリにするためには、Meta XR SDKをプロジェクトに追加する必要があります。
そのために、まずはUnityのアセットストアから必要なアセットに対して[Add to My Assets]をクリックしてUnity Editorで参照できるようにします。
assetstore.unity.com
今回使用するMeta XR SDKは次のものになります。
インポート
My Assetsに追加出来たらUnity Editorでインポートします。
そのためには、Unity Editorで[Window]-[Package Manager]メニューをクリックして、Package Mangerを表示します。
[Packages]を「My Assets」に変更して3つのSDKをインポートします。
Meta XR Feature Setは有効にしない
MRTK3とMeta XR SDKを併用した場合、次のようなダイアログが表示されます。
必ず[Cancel]ボタンをクリックしてください。
Validationの解消
インポートが終わったら、[Edit]-[Project Settings]メニューでリストから[Oculus]を選択します。
[Checklist]の各項目の[Fix]ボタンをクリックします。
最終的に次の2つ以外が解消されればOKです。
- Oculus must be added to the XR Plugin active loaders
- Unity's OpenXR Plugin is not recommended when using the Oculus SDK, please use Oculus XR Plug-in instead
ターゲットプラットフォーム指定
Unity Editorで[File]-[Build Setting]で、Platfromで「Android」を選択してから、[Switch Platform]をクリックしてターゲットプラットフォームを切り替えます。
Player設定
[Edit]-[Project Setting]メニューで[Player]を選択します。
Meta Quest 3用に設定を整えます。
- [Other Settings]-[Rendering]-[Color Space]:Linear
- [Other Settings]-[Rendering]-[Auto Graphics API]:チェックを外す
- [Other Settings]-[Rendering]-[Multithreaded Rendering]:チェック
- [Other Settings]-[Identification]-[Minimum API Level]:Android 10.0 Marshmallow (API level 29)
- [Other Settings]-[Identification]-[Target API Level]:Automatic (highest installed)
- [Other Settings]-[Configuration]-[Install Location]:Automatic
Quality設定
[Edit]-[Project Setting]メニューで[Quality]を選択します。
- [Rendering]-[Pixel Light Count]:1
- [Rendering]-[Anti Aliasing]:4x Multi Sampling
- [Textures]-[Global Mipmp Limit]:0:Full Resolution
- [Texture]-[Anisotropic Textures]:Per Texture
- [Particles]-[Soft Particles]:チェックを外す
- [Terrain]-[Billboards Face Camera Position]:チェック
MRTKプロファイル作成
Unity Editorで[Edit]-[Project Settings]メニューで[MRTK3]を選択します。
[Android settings]タブを選択して[Assign MRTK Default]ボタンをクリックします。
警告マークがでますが[Profile]欄が「MRTKProfile (MRTK Profile)」となっていればOKです。
XR Plugin Management (Open XR) の設定
インストール
Unity Editorで[Edit]-[Project Settings]メニューで[XR Plug-in Mangement]を選択します。
[Android Settings]タブを選択して[OpenXR]と[OpenXR]-[Meta XR feature group]をチェックします。
OpenXRの設定
[Edit]-[Project Settings]メニューで[XR Plug-in Mangement]-[OpenXR]を選択して、OpenXRの設定を行います。
- Enabled Interaction Profile:List is Empty
- Hand Tracking:チェック
- Meta Quest Support:チェックを外す
- Motion Controller Model:チェック
Validationの解消
[Edit]-[Project Settings]メニューで[XR Plug-in Mangement]-[Project Validation]を選択して、エラーや警告がないかを確認します。
エラーや警告の行で[Fix]ボタンが表示されているものは、順次クリックして解消します。
ただし、現状は次の2つについては解消できないので、この2つの[Fix]は無視します。
- [Packages] Unity's OpenXR Plugin is not recommended when using the Oculus SDK, please us Oculus XR Plug-in insted
- [Compatibility] Build Target (Unknown) is not supported
ビデオシースルー設定
Main Camera設定
[Hierarchy]タブで[MRTK XR Rig]-[Camera Offset]-[Main Camera]を選択し、[Inspector]タブの[Camera Setting Manager]-[Opaque Display]を次のように設定します。
- Clear Mode: Solid Color
- Clear Color: 0, 0, 0, 0
[Transparent Display]についても同様に設定します。
SeeThroughオブジェクトの追加
- [Hierarchy]タブの任意の場所を右クリックして[Create Empty]メニューを選択して、空のGameObjectを追加します。
- 追加したオブジェクトの名前を「SeeThrough」にします。
- 「SeeThrough」オブジェクトを選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Scripts]から「OVR Manager」「OVR Passthrough Layer」を追加します。
OVR Managerの設定
[Target Devices]-[Quest 3]をチェック、[Insight Passthrough]-[Enable Passthrough]をチェックします。
[Insight Passthrough]セクションが変更不可の場合は、[Edit]-[Project Settings]-[Oculus]の[CheckList]でエラーが表示されていないかを確認して、エラーを[Fix]してから再度試してみてください。
OVR Passthrough Layerの設定
[Placement]を「Underlay」、[Opacity]を「1」にします。
途中実行
ここまでの設定でビデオシースルーモードでの実機実行が可能です。
試しに、Meta Quest 3をUSB接続して[File]-[Build And Run]メニューでアプリを実機転送して実行してみましょう。
Cubeをつかんで投げることができました。
www.youtube.com
重力加速度を適用していないので無重力状態でどこまでも飛んでいきます。
壁や床を検出する
Meta Quest 3ではシーン(Unityのシーンとは別のもの)という機能で、実際の空間をスキャンして壁や床を検出して仮想的なルームを作成することができます。いわゆる空間マッピングと呼ばれるものです。
検出した壁や床などに対してColliderを設定するこることでUnity内のオブジェクトが壁や床と相互作用ができるようになります。
先ほどまでは、Cubeを投げるとずっと飛んで行ってしまいましたが、相互作用ができれば壁や床で跳ね返るような動きが実現できます。
空間マッピングオブジェクトの追加
- [Hierarchy]タブの任意の場所を右クリックして[Create Empty]メニューを選択して、空のGameObjectを追加します。
- 追加したオブジェクトの名前を「OVRSceneManager」にします。
- 「OVRSceneManager」オブジェクトを選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Scripts]から「OVR Scene Manager」「OVR Scene Model Loader」を追加します。
「OVR Scene Manager」で管理する壁や床のオブジェクトは[Plane Prefab]およぶ[Volume Prefab]に設定します。単なるオブジェクトではなく「Prefab」形式で指定します。
Plane Prefabの作成
- [Project]タブの[Assets]-[Scenes]を左クリックし、[Create]-[Prefab]で新しいPrefabを追加します。
- 追加したPrefabの名前を「OVRScenePlane」にします。
- 「OVRScenePlane」Prefabを選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Scripts]から「OVR Scene Anchor」「OVR Scene Plane Mesh Filter」の2つを追加します。
- 「OVRScenePlane」Prefabを選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Mesh]から「Mesh Filter」「Mesh Renderer」の2つを追加します。
- 「OVRScenePlane」Prefabをダブルクリックして、[Hierarchy]タブに「OVRScenePlane」Prefabを表示します。
- [Hierarchy]タブの任意の場所を右クリックして[Create Empty]メニューを選択して、「OVRScenePlane」Prefabに空のGameObjectを追加します。
- 追加したGameObjectの名前を「Collider」にします。
- 「Collider」を選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Physics]から「Box Collider」を追加します。
- Box ColliderのSizeを(1, 1, 0.01)にします。
Volume Prefabの作成
- [Project]タブの[Assets]-[Scenes]を左クリックし、[Create]-[Prefab]で新しいPrefabを追加します。
- 追加したPrefabの名前を「OVRSceneVolume」にします。
- 「OVRSceneVolume」Prefabを選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Scripts]から「OVR Scene Anchor」「OVR Scene Plane Mesh Filter」の2つを追加します。
- 「OVRSceneVolume」Prefabを選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Mesh]から「Mesh Filter」「Mesh Renderer」の2つを追加します。
- 「OVRSceneVolume」Prefabをダブルクリックして、[Hierarchy]タブに「OVRSceneVolume」Prefabを表示します。
- [Hierarchy]タブの任意の場所を右クリックして[Create Empty]メニューを選択して、「OVRSceneVolume」Prefabに空のGameObjectを追加します。
- 追加したGameObjectの名前を「Collider」にします。
- 「Collider」を選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Physics]から「Box Collider」を追加します。
- [Hierarchy]タブの任意の場所を右クリックして[Create Empty]メニューを選択して、「OVRSceneVolume」Prefabに空のGameObjectを追加します。
- 追加したGameObjectの名前を「Mesh」にします。
- 「Mesh」を選択し、[Inspector]タブで[Add Component]ボタンをクリックして、[Mesh]から「Mesh Filter」「Mesh Renderer」の2つを追加します。
- [Hierarchy]タブの任意の場所を右クリックして[Create Empty]メニューを選択して、「OVRSceneVolume」Prefabに空のGameObjectを追加します。
Prefabの設定
2つのPrefabの準備ができたならば、[Hierarchy]タブで「OVRSceneManager」オブジェクトを選択し、[Inspector]タブで[Plane Prefab]およぶ[Volume Prefab]に設定します。
完成品動作
部屋の壁や床を認識して、無重力状態のCubeが部屋の中から飛び出していかない設定が以上で完成しました。
実機に転送して動作を確認してみましょう。
www.youtube.com
まとめ
本エントリの前半の「実装」部分は、MRTK3でアプリを作成するときの「機種依存しない」部分になります。
「Meta Quest 3 固有機能の実装」部分で、Meta Quest 3固有の設定、ビデオシースルー、空間認識を実装しています。この3点は、デバイスが異なる場合も必要な作業は同じで実現手順が異なりますので、HoloLensやXreal Airなどの実装もそのうちご紹介したいと思います。
次回は、現実空間と仮想オブジェクトのオクルージョンなども確認していきたいと思います。
雑感
Meta Quest 3も壁や床の認識過程を見ると空間スキャンした結果をメッシュ構造で取得しているようですが、最終的には「ルーム」という四角い部屋のような面で当たり判定をしています。
HoloLensのようにメッシュそのものをつかってくれればいいのですが、もし、実現するのであれば、実際の部屋の少し外側になるようにルームを設定し、その中でメッシュ状に認識している空間スキャン結果を自前でオブジェクトを張り付けるようなそんなコードが必要なのかもしれません。
でも、ルームという考え方は空間スキャン結果のオブジェクト数を最小(壁4平面+床と天井の2平面=6平面)におさえることができて、結果的に快適なMR空間を演出できる手法ではあります。