Unity + Meta Quest開発メモ
最終更新日:2026年08月12日記事作成日:2019年06月09日
UnityでQuest対応アプリを開発する方法やTipsをまとめています。
更新履歴
(2026年8月12日)「ハンドトラッキングが効かないときは」を追加
(2026年8月4日)古い記述を一通り更新、Build and Run直後の黒画面、Meta Quest Agentic Tools、Project Setup Toolが開かないようにする方法について追記、Meta Questで目の前に窓が張りつくような表示乱れが発生するを追加
(2026年6月13日)「提供元不明」が出てこない問題について注記
(2026年5月25日)「パススルー機能を使うには」を最新のMeta XR Core SDKにあわせて更新
(2026年4月25日)Meta Horizon OS v201以降の新しいUIに合わせて「Build and Runしたアプリを再度実行するには」「アプリの権限を確認するには」をリライト
UnityでQuest対応アプリを作るには
UnityのQuest対応の概要
Meta QuestのアプリはUnityを使用して開発できます。QuestはAndroidベースですので、Androidアプリとしてビルドします(通常のAndroidスマートフォンと異なりGoogle Playが入っていないため要注意です)。
Unityの標準機能だけでもQuestで動くVRアプリは開発できますが、Quest固有の機能やMetaプラットフォームの機能を利用する場合はAsset Storeで公開されているMetaのSDKパッケージ群を使用します。以降本ページではMetaのSDKベースで解説します。
開発用のPC・OSは何を使えばいいの?
Quest開発にはWindows 11のゲーミングPCがおすすめです。アプリ開発中にUnityで再生ボタンを押すだけでMeta Horizon Link(Quest Link)で動作を確認できます。macOSや、ゲーム用のGPUを搭載していないWindows機でも開発できますが、毎回ビルドしてQuest実機に転送しないとVRで確認できません。
下記ページにMeta Horizon Link(Quest Link)が動作するWindows PCの推奨スペックが掲載されています。英語からの翻訳ページのため「X」の印が日本語の「○」の意味なので注意してください。
Unityのバージョンはどれを使えばいいの?
MetaのSDKが対応しているUnityのバージョンは Set up Unity for VR developmentのページで確認できます(日本語ページは情報が古い場合があるので注意してください。ページの左下で言語設定を切り替えられます)。2026年6月現在、Unity 2022.3.15以降が必要、Unity 6.1以降を推奨となっています。
なお、Unity 2022ではビルドその他のトラブルが多数発生しています。「Unity 2022でのトラブル」を参照してください。
Questを開発者モードにする
Questで自作のアプリが動くようにするには、「開発者モード」にする必要があります。スマートフォンにインストールしたMeta Horizonアプリの左上のメニューボタンをタップし、「デバイス」で接続されているデバイスを選択すると「ヘッドセットの設定」の中に「開発者モード」がありますのでオンにしてください。
なお、開発者モードにするには、Metaアカウントの2要素認証を有効にするか決済方法を設定する必要があります。
開発者モードを有効にしたQuestをPCにUSBケーブルで接続すると、Questの画面に「USBデバッグを許可しますか?」というダイアログが開きますので許可します。
Questアプリをビルドするには
Questアプリをビルドする手順を示します。
Unity HubでUnityをインストールする
Unity HubでUnityをインストールします。インストールするときに、モジュールの追加でAndroid Build Supportのところにすべてチェックを入れてください。
Unityでプロジェクトを作成する
新規プロジェクトを「3D(URP)」テンプレートで作成し、Build SettingsでAndroidプラットフォームに切り替えます。
Meta XR Core SDKをインポートする
Asset StoreでMetaのSDKパッケージ一式が公開されています。最低限必要なコアパッケージはMeta XR Core SDKになりますので、こちらをプロジェクトにインポートします。
インストールすると、以下の2つのダイアログが表示されます。
- Metaに情報を送るかどうかという「Help improve the Oculus SDKs」ダイアログが出てくるのでお好みでどちらかのボタンをクリック
- 新しいOVRPluginを認識しましたというダイアログが出るので「Restart Editor」をクリックしてUnityエディタを再起動
プロジェクトの推奨設定をする
Unityが再起動すると、左上に赤いドットのついた「Meta XR Tools」のボタンが追加されています。
これをクリックして「Project Setup Tool」を選択すると、以下のようなProject Settingsのページが開きます。このページで、UnityのXRプラグインの有効化や各種推奨設定を一括で自動的に行うことができます。ひとまずWindowsとAndroidのタブでそれぞれ「Fix All」をクリックして全部緑にしてください。
なお、プロジェクトを開くときにいつもProject Setup Toolのダイアログが表示されて煩わしいことがあります。Project Setup Toolのページの右上の歯車をクリック、Background Checksをオフで無効化できます。
プロジェクトの設定を確認する
プロジェクトがどうなっているか簡単に確認してみましょう。
UnityのXRプラグインシステムであるXR Plug-in Managementが有効化され、Project Settings > XR Plug-in ManagementのAndroidタブでOpenXRが有効になっていることを確認します。Unity 6以降の新規プロジェクトではUnity OpenXR Pluginが推奨です。
Project Settings > XR Plug-in Management > OpenXRでは、Meta Quest Supportなどの必要なFeature GroupとInteraction Profileを確認します。Depth APIを使用する場合はPackage ManagerからUnity OpenXR: Meta(com.unity.xr.meta-openxr)もインストールします。
Oculus XR Pluginは非推奨で、将来削除される予定です。Unity 6未満かつMeta XR SDK v74未満の既存プロジェクトを保守する場合に限り、旧構成としてOculus XR Pluginを使用します。
パッケージ名をつける
QuestアプリはProject SettingsのPlayer > Package Nameをもとに識別されます(つまり、Package Nameを変えると別のアプリとして認識されます)。通常、ドメイン名を逆順にした「com.[会社名].[プロダクト名]」のような名前をつけます。
サンプルシーンをビルド・実行する
Package ManagerのMeta XR Core SDKのページのSamplesタブからサンプルシーンをインストールできます。
インストールしたら、試しにAssets/Samples/Meta XR Core SDK/(バージョン)/Sample Scenes/ControllerModelsシーンを開いてみてください。
Build Settingsを開き、開発者モードにしたQuestを接続してBuild and Runボタンを押し、適当な.apkファイル名を指定するとビルドと実機への転送が始まります。初回のビルドはPCの性能により3分から10分程度の時間がかかりますが、2回目以降はずっと短い時間で済みます。成功するとアプリが起動し、コントローラーのスティックで移動・回転できます。
ビルドしても動かないときは
- Quest上で一度アプリをアンインストールしてBuild and Runし直すと上手くいく場合があります(別のPCでビルドした場合や、Package Nameが衝突した場合など)。
- Project Setup Toolでプロジェクトの問題がレポートされるので確認します。
- Window > Package ManagerでXR Plug-in Management、OpenXR Plugin、Unity OpenXR: Meta、Meta XR Core SDKのバージョンと互換性を確認します。
- Build and Run直後に画面に何も表示されない場合は、電源ボタンで一度スリープさせて復帰するとアプリが起動することがあります。
Build and Runしたアプリを再度実行するには
(Meta Horizon OS 2.1以降)ビルドして実機に転送したアプリは、Questに格納されていていつでも実行できます。コントローラーのMetaボタンを押して下のツールバー中央の「ライブラリ(Library)」を選択、左端の「メニュー(Menu)」アイコンから「提供元不明(Unknown Source)」を選択すると出てきます。
個々のアプリの右端の「…」ボタンから削除(アンインストール)することもできます。
Unityのエディタで再生するには
専用GPUを搭載したWindows機では、Meta Horizon LinkソフトウェアをインストールしてMeta QuestをMeta Horizon Linkで接続すると、Unityのエディタ上でシーンをVRで再生できます。ビルドしなくても動作確認ができるため開発が楽になります。VRモードで再生するには、Project Settings > XR Plug-in ManagementのWindowsタブでInitialize XR on StartupとOpenXRを有効にし、Meta Horizon LinkをアクティブなOpenXRランタイムに設定してください。
さらに、Meta Horizon Linkソフトウェアの 設定 > ベータ > 開発者ランタイム機能 をオンにすると、Meta Horizon Linkでカメラパススルーも動作させられます。
エディタ再生でフレームレートが出ない場合は、Gameウィンドウの右上のバーでPlay Maximizedを選択してウィンドウが最大化されるようにするとフレームレートが出ることがありまます。
Questのログ出力を見るには
UnityのAndroid Logcatパッケージをインストールすると、Quest実機のエラー出力等を確認できます。Window > Package Managerで左上のPackagesをUnity Registryにすると出てきます。
Build and Runすると自動的にデバイスに接続してUnityのウィンドウにログが表示されます。キーワードでフィルタをかけたり、スクリーンショットを撮ることもできます。
また、Memory Windowを表示していると定期的にフレーム落ちするようなので無効にしておいたほうがよさそうです(Tools > Memory Window > Disabled)。
アプリの権限を確認するには
(Meta Horizon OS 2.1以降)ビルドしたアプリが要求している権限がきちんと有効になっているかを確認したい場合があります。
Build and Runでインストールしたアプリの場合
コントローラーのMetaボタンを押して下のツールバーから「クイックコントロール(Quick control)」をクリックし、左端の歯車アイコンをクリック、左の「プライバシーと安全(Privacy & Safety)」タブを選択し、「インストール済みのアプリ(Installed apps)」を選択するとアプリ一覧が表示されます。開発環境からインストールしたアプリは下のほうに出てくるのでスクロールしてください。
ダッシュボードやストアから配信したアプリの場合
「ライブラリ(Library)」のアプリ一覧でアプリをポイントしてトリガーを長押しするとメニューが出てきますので、「設定(Settings)」で確認できます。
MetaのSDKをアップデートするには
Package ManagerのIn Projectで個別のSDKをアップデートしてください。
Meta Quest Developer Hubについて
Meta Quest Developer Hubという開発用のポータルツールが提供されています。ヘッドセット内の映像の中継表示や、ガーディアンや近接センサーの無効化、アプリの起動やアンインストール、Meta Horizon Linkの起動、Metaが提供するツールのダウンロード、ダッシュボードへのアプリのアップロード等が簡単にできるようになっていますので、インストールしておくと便利です。
なお、Meta Quest Developer Hubはadbコマンドが組み込まれており、UnityもデプロイやAndroid LogcatでUnity組み込みのadbコマンドを使用するため、両方同時に使用しようとすると衝突して正常に動作しません。たとえばUnityで下記のようなエラーが出ます。
Multiple ADB server instances found, the following ADB server instance have been terminated due to being run from another SDK. Process paths:
C:\Program Files\Oculus Developer Hub\resources\bin\adb.exe
対策として、Meta Quest Developer HubでUnity組み込みのadbコマンドを使用するように設定します。Meta Quest Developer HubのSettings > General > ADB PathのEditを押し、Detected ADB Clientsから使用しているUnityのバージョンのadb.exeを設定して右下のRestart MQDHで再起動してください。
Meta Quest Agentic Toolsについて
Meta Quest Agentic Toolsは、Meta Questを制御するコマンドラインツールと、開発を補助するスキル一式です。Claude Code、Codex、Cursor等のAIコーディングエージェントから利用できます。
使用するには、まずGitHub CLIをインストールして、下記gh skillコマンドを使用するのが簡単です。
gh skill install meta-quest/agentic-tools
実行すると、インストールするスキルとエージェント、スコープをそれぞれ尋ねてきます。なおスキルは約30個あり、グローバルにインストールすると都度エージェントが参照してしまうので、プロジェクト単位で必要なときにインストールしたほうがいいです。
インストールされたスキルでは、コーディングエージェントがMeta Questの公式ドキュメントを参照しやすくするほか、Unityプロジェクトのセットアップとコードレビュー、Platform SDK、ストア提出、パフォーマンス解析等の開発手順がまとめられています。AIは指示やプロジェクトの内容に応じて必要なスキルを参照し、最新の公式情報とMeta Quest向けのベストプラクティスを確認しながら作業できるようになります。
また、エージェントから開発者モードのQuestを操作できます。接続した端末の情報取得と再起動、アプリのインストール・起動・停止、ログとスクリーンショットの取得、ファイル操作、Perfettoによるパフォーマンス計測、Meta公式ドキュメントの検索等に対応しています。たとえば、アプリが起動しない問題についてAIに調査を依頼すると、実機ログを参照して原因の切り分けを手伝ってもらえます。
Meta XR Simulatorについて
ヘッドセットがなくてもMeta Questの動作をシミュレートできるOpenXRランタイムが提供されています。
Asset StoreのMeta XR Simulatorでパッケージをインストールしたのち、メニューのOculus > Meta XR Simulator > Activateを有効にしてUnityの再生ボタンを押すと下のようなシミュレーター画面が開きます。
[、]キーで操作対象(ヘッドセットと左右モーションコントローラー)を変更して、以下の要領で移動操作ができます(一部のみ。ボタン操作等の詳細はMeta XR SimulatorのInput Bindingsの表示を確認してください)。
| キーボード・マウス | 操作 |
|---|---|
| マウス右ドラッグ | 回転 |
| マウス中ドラッグ | 上下左右移動 |
| マウス左クリック | トリガー |
| WASD | 前後左右移動 |
| Q/E | 左右ロール |
また、MR開発をサポートするSynthetic Environment Serverという機能があり、Meta > Meta XR Simulator > Synthetic Environment Serverでサーバーを立ち上げておくとカメラパススルー等をテストできます。その他さまざまな開発補助機能が用意されています。
Building Blocksについて
Meta XR Core SDKにはBuilding Blocksという機能があり、Meta > Tools > Building Blocks(SDKのバージョンによってはMeta XR Tools > Building Blocks)から開けます。必要な機能を選ぶだけでカメラリグを組み立てたり、依存コンポーネントやプロジェクト設定を追加したりできます。
Oculus Integrationから移行するには
Oculus Integartionは非推奨になり、Quest開発はMetaの新しいSDKパッケージを使用するようになりました。Meta XR Core SDKにOculus IntegrationのAssets/VRフォルダ相当が含まれているほか、これまでにOculus Integrationに入っていたものが個別のパッケージに分散しています。
新しいSDKパッケージに更新するには、Unityをいったん終了して(プラグインのDLLを解放するために必要です)、プロジェクトのバックアップを取るかバージョン管理した状態でAssets/Oculusフォルダを削除し、Unityを開き直して必要なパッケージをインストールしてください。
なお、Oculus IntegrationのSampleFrameworkフォルダの内容はUnity-StarterSamplesに移動しています。
MetaのSDKパッケージ一覧
Asset StoreでMetaのSDKパッケージ一式が公開されていますが、個々のパッケージの内容について説明します(Meta XR Simulator関連とVoice SDK関連はいったん除いています。あとで個別の機能の項目に分ける予感)。
コアパッケージ
Meta XR Core SDK
最低限必要なパッケージです。従来のOculus IntegrationのVRフォルダ相当が含まれていて、パッケージのSamplesから基本的なサンプルシーンがインストールできます。
Interaction SDK関連のパッケージ
以下がInteraction SDK関連のパッケージで、Interaction SDKを使用する場合、基本的にはすべてインストールします。
Meta XR Interaction SDK
Interaction SDKのパッケージです。
Avatars SDK関連のパッケージ
Meta Avatars SDK
Avatars SDKのコアパッケージです。パッケージのSamplesにサンプルシーンが含まれています。
Meta Avatars SDKはEnd-of-Featureとなっており、40.0.1が最終リリースです。既存アプリの保守や提出は継続できますが、新機能やAPIの追加は予定されていません。
Meta Avatars SDK Sample Assets
プリセットアバターのアセットが含まれています。インポートすると60~100MB超のzipファイルがAssets/Oculusフォルダに数個コピーされるので(中身は多数の.glbファイルです)、GitHubにpushする場合はLFSが必要になります。
その他のパッケージ
Meta XR Platform SDK
マッチメイキング、DLCやアプリ内課金、クラウドストレージ、実績等のMetaのプラットフォーム機能が入っています。
Meta MR Utility Kit
パススルーを使用したMRアプリ開発のためのScene API関連の機能が入っています。
Meta XR Audio SDK
3Dサウンド関連の機能が入っています。詳しくは、3Dサウンドを使用するにはを参照してください。
Meta XR Haptics SDK
波形ベースの高レベルなコントローラー振動機能が入っています。
Meta XR All-in-One SDK
All-in-One SDKは、Meta XRの主要パッケージ一式への依存関係をまとめたパッケージです。Oculus Integrationから移行する場合や、Building Blocksを幅広く使用する場合はAll-in-One SDKが便利です。必要な機能が限定されている場合は、Core SDKやMR Utility Kitなどを個別にインストールするとプロジェクトを小さく保てます。
各パッケージのサンプルは、Package Managerから対象パッケージを選択して個別にインポートします。
プロジェクトの基本設定について
プロジェクトの各種設定は、Unity上部のMeta XR Toolsメニュー、または Meta > Tools > Project Setup Tool から開けるProject Setup Toolで確認できます。自動修正できる項目はFixを使用し、選択の余地があるものについて以下で説明します。
レンダリングパイプライン
レンダリングパイプラインはビルトインまたはUniversal Render Pipelineが使用できます
Unity 2021から2023あたりにかけて、URP 11以降でパフォーマンスが出ないという問題がUnityの公式フォーラム等で長らく報告されていましたが、該当IssueはUnity 2022.3.11と2023.1.14で修正されています。新規プロジェクトではMetaが推奨するUnity 6.1以降と、対応するURPパッケージを使用してください。
アンチエイリアス
Project Settings > Quality > Anti Aliasingで設定します。2xはとても軽量でかつ効果が大きいので最低でも必ずかけておいたほうがいいです。4xはポリゴンのエッジがさらにすっきりしますが若干重めです。フラグメントシェーダーが重いシェーダーで画面の広範囲が覆われたときに負荷増が顕著になります。8xは4xと違いが分からず、4xまでしか効かない感じがします。
OpenGL ESかVulkanか
Unity OpenXR PluginではOpenGL ESとVulkanの両方を使用できます。新規プロジェクトではProject Setup Toolの推奨に従い、使用する機能とレンダリングパイプラインに合わせて選択してください。
Depth API、Application SpaceWarp等、Vulkanが必須の機能があります。Depth APIではVulkanに加えてStereo Rendering ModeをMultiviewにする必要があります。
一方で、アセットによってはVulkan未対応のものがあったりするので要注意です。例えばAVPro Videoが長らくVulkanで動きませんでしたが、v3で対応したようです。
IL2CPP
Metaにアプリを提出する場合はProject SettingsでScripting BackendをIL2CPPにしてARM64でビルドする必要があります。が、IL2CPPビルドはとても時間がかかるので、開発中や、ストアにリリースするつもりのない制作物ではMonoでいいかもしれません。
なお、MonoビルドはIL2CPPビルドと比べてCPU処理の負荷が数倍増えることがあります。また、カメラパススルー等、IL2CPPビルドにしないと動かない機能があるので注意してください。
VRのカメラ配置の基本
UnityのシーンをQuestのVRモードに対応するには、デフォルトで作成されているMain Cameraを削除して、代わりにPackages/Meta XR Core SDK/Prefabs/OVRCameraRigプレハブをシーンに配置します。プレハブに追加されているOVRCameraRig.csによって、OVRCameraRigの孫のCenterEyeAnchorがヘッドセットの動きに追従します。
OVRCameraRigプレハブは、デフォルトではシーン内のプレイヤーの視点の位置(正確には両目の中間の位置)に配置します(Unityのシーンの1ユニットが1メートルになります)。その上で、アプリの実行中に、ちょうどいい場所に立つ、椅子に深く座るなどしてコントローラーのOculusボタンを長押しすると位置合わせ(リセンター)ができます。
なお、Unityのデフォルト状態だとSceneウィンドウに表示されるカメラアイコンが大きすぎて位置調整がしづらいと思います。Sceneウィンドウの右上のボタンをプルダウンして、3D Iconsのスライダーを左に動かしてみてください。
立って体験するアプリを作るには
OVRCameraRigプレハブをシーンの地面と同じ高さに配置して、OVR ManagerコンポーネントのTracking Origin TypeをFloor LevelまたはStageに変更します。
Floor Levelだとリセンターができる、Stageだとリセンターができないという違いがあります。Floor Levelにするとヘッドセットをはずしてかぶり直したときにリセンターがかかるので、ルームスケールやアリーナスケール等、立って歩きまわるアプリを開発する場合はStageにします。Stageでは境界線の中央がシーンの原点になります(ただし、Meta Horizon Linkでの実行ではStageにしてもヘッドセットの脱着でリセンターがかかります)。
adbコマンドについて
adb (Android Debug Bridge)はGoogleから提供されているAndroidデバイスの各種操作を行うためのコマンドラインツールです。Questでも使用できます。
adbコマンドは下記ページからダウンロードできるほか、UnityやMeta Quest Developer Hubに同梱されています。異なるバージョンのadbコマンドを同時に使用すると衝突して動かないことがあるので注意が必要です。adb kill-serverを実行すると動くようになる場合があります。
よく使うコマンドをいくつか紹介します。
Questの接続を確認するには
$ adb devices
アプリをアンインストールするには
$ adb uninstall [パッケージ名]
パッケージ名は、Questのアプリ > 提供元不明 で確認したり、下記コマンドで一覧表示できます。
インストールされているアプリの一覧を表示するには
$ adb shell cmd package list packages
apkファイルをインストールするには
$ adb install [apkファイル]
アプリを実行するには
下記コマンドでUnityでビルドした指定パッケージ名のアプリを実行できます。
$ adb shell am start -n [パッケージ名]/com.unity3d.player.UnityPlayerActivity
Questを再起動するには
$ adb reboot
Questの内部ストレージを見るには
下記コマンドでアプリのデータを格納するフォルダを見ることができます。
$ adb ls /sdcard/Android/data
Questの内部ストレージにファイルを格納するには
$ adb push [ファイル名] /sdcard/Android/data/[パッケージ名]/files
TODO: 「データを保存するには」あたりの項目を作る
QuestのIPアドレスを確認するには
$ adb shell ip addr
近接センサーを無効化するには
$ adb shell am broadcast -a com.oculus.vrpowermanager.prox_close
近接センサーを有効化するには
$ adb shell am broadcast -a com.oculus.vrpowermanager.automation_disable
モーションコントローラーについて
Questのモーションコントローラーは、コントローラーに埋め込まれた赤外線LEDをQuest本体の赤外線カメラで位置トラッキングする仕組みになっています。バッテリーは左右それぞれ単三電池一本です。エネループ等も使用できます。
コントローラーをVR空間に表示するには
OVRCameraRigのLeftControllerAnchorおよびRightControllerAnchorにOVRControllerPrefabをアタッチして、左手のOVRControllerPrefabのControllerをL Touchに、右手のOVRControllerPrefabのControllerをR Touchに設定してください。
なお、Meta XR Core SDKのサンプルシーンのControllerModelsシーンに上記セットアップ済みのOVRCameraRigがあります。
コントローラーの操作で動く手を表示するには
TODO:要再確認
OVRCameraRigのLeftHandAnchorにCustomHandLeftを、RightHandAnchorにCustomHandRightをアタッチすると、コントローラーの操作で動く手を表示できます。
Meta XR Core SDKのHandsTestシーンに上記セットアップ済みのOVRCameraRigがあります。
コントローラーの位置を取得するには
コントローラーの位置は、OVRCameraRigのLeftHandAnchor、RightHandAnchorのTransformを参照するほか、OVRInput.GetLocalControllerPosition / GetLocalControllerRotationで取得することもできます。
トリガーやボタンの状態を取得するには
OVRInputクラスでTouchのボタン・スティック・トリガーの状態を取得できます。
OVRInputは異なる種類のコントローラーの入力を抽象化して取得できるようになっていますが、ややこしいので、とにかくTouchの入力を一通り読む方法をコードの形で示します。正確なところは OVRInputのドキュメントページを参照してください。
ボタン・トリガーを押したか調べるには
if (OVRInput.GetDown(OVRInput.RawButton.A))
{
Debug.Log("Aボタンを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.B))
{
Debug.Log("Bボタンを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.X))
{
Debug.Log("Xボタンを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.Y))
{
Debug.Log("Yボタンを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.Start))
{
Debug.Log("左手メニューボタンを押した(オン・オフ不安定なので注意)");
}
if (OVRInput.GetDown(OVRInput.RawButton.RIndexTrigger))
{
Debug.Log("右人差し指トリガーを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.RHandTrigger))
{
Debug.Log("右中指グリップを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.LIndexTrigger))
{
Debug.Log("左人差し指トリガーを押した");
}
if (OVRInput.GetDown(OVRInput.RawButton.LHandTrigger))
{
Debug.Log("左中指グリップを押した");
}
GetDownではなくGetを使うと押しっぱなしの状態でtrue、GetUpでリリースの瞬間にtrueになります。
なお、右手のOculusボタンの状態は取得できません。
トリガーの入力をアナログ値で取得するには
// 右人差し指トリガー
float rTrigger1 = OVRInput.Get(OVRInput.RawAxis1D.RIndexTrigger);
// 右中指グリップ
float rTrigger2 = OVRInput.Get(OVRInput.RawAxis1D.RHandTrigger);
// 左人差し指トリガー
float lTrigger1 = OVRInput.Get(OVRInput.RawAxis1D.LIndexTrigger);
// 左中指グリップ
float lTrigger2 = OVRInput.Get(OVRInput.RawAxis1D.LHandTrigger);
離すと0.0、押し込むと1.0になります。ただし、完全に押し込んでも1.0まで上がらなかったり、すぐに1.0にならなかったりしますので、押し込んだかどうか判定する場合には閾値を設ける必要があります。
選択、キャンセル入力を取得するには
Button.One、Twoを使用すると便利です。それぞれTouchのA/Xボタン、B/Yボタンにマップされていますが、セットアップ時の説明にも表示されるスタンダードな操作となっています。
if (OVRInput.GetDown(OVRInput.Button.One))
{
Debug.Log("選択した");
}
if (OVRInput.GetDown(OVRInput.Button.Two))
{
Debug.Log("キャンセルした");
}
アナログスティックの入力を取得するには
下記で取得できます。Vector2のX軸が左-1.0~右1.0、Y軸が下-1.0~上1.0になっています。
// 左手のアナログスティックの向きを取得
Vector2 stickL = OVRInput.Get(OVRInput.RawAxis2D.LThumbstick);
// 右手のアナログスティックの向きを取得
Vector2 stickR = OVRInput.Get(OVRInput.RawAxis2D.RThumbstick);
アナログスティックをボタンとして押し込むこともできます。
if (OVRInput.GetDown(OVRInput.RawButton.LThumbstick))
{
Debug.Log("左アナログスティックを押し込んだ");
}
if (OVRInput.GetDown(OVRInput.RawButton.RThumbstick))
{
Debug.Log("右アナログスティックを押し込んだ");
}
また、デジタル4方向の入力も取得できます。メニュー選択等に便利です。
if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickUp))
{
Debug.Log("左アナログスティックを上に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickDown))
{
Debug.Log("左アナログスティックを下に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickLeft))
{
Debug.Log("左アナログスティックを左に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.LThumbstickRight))
{
Debug.Log("左アナログスティックを右に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.RThumbstickUp))
{
Debug.Log("右アナログスティックを上に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.RThumbstickDown))
{
Debug.Log("右アナログスティックを下に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.RThumbstickLeft))
{
Debug.Log("右アナログスティックを左に倒した");
}
if (OVRInput.GetDown(OVRInput.RawButton.RThumbstickRight))
{
Debug.Log("右アナログスティックを右に倒した");
}
ボタン・スティック・トリガーに触れているか調べるには
中指グリップとメニューボタン、Oculusボタン以外について、指が触れているかどうかを調べることができます。
if (OVRInput.Get(OVRInput.RawTouch.LIndexTrigger))
{
Debug.Log("左人差し指用トリガーに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.LThumbstick))
{
Debug.Log("左アナログスティックに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.RIndexTrigger))
{
Debug.Log("右人差し指用トリガーに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.RThumbstick))
{
Debug.Log("右アナログスティックに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.A))
{
Debug.Log("Aボタンに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.B))
{
Debug.Log("Bボタンに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.X))
{
Debug.Log("Xボタンに触れている");
}
if (OVRInput.Get(OVRInput.RawTouch.Y))
{
Debug.Log("Yボタンに触れている");
}
近接センサーの入力を調べるには
人差し指用トリガーとアナログスティックには近接センサーがあり、指が近づいた(ちょっと浮いている)状態を取得できるようになっています。
if (OVRInput.Get(OVRInput.RawNearTouch.LIndexTrigger))
{
Debug.Log("左人差し指用トリガーの近くに指がある");
}
if (OVRInput.Get(OVRInput.RawNearTouch.LThumbButtons))
{
Debug.Log("左アナログスティックの近くに指がある");
}
if (OVRInput.Get(OVRInput.RawNearTouch.RIndexTrigger))
{
Debug.Log("右人差し指用トリガーの近くに指がある");
}
if (OVRInput.Get(OVRInput.RawNearTouch.RThumbButtons))
{
Debug.Log("右アナログスティックの近くに指がある");
}
この近接センサーを使用して、指をさしている状態を取得できます。人差し指を伸ばすとRawNearTouch.RIndexTriggerがfalseになります。
コントローラーを振動させるには
OVRInput.SetControllerVibrationを使用します。周波数と振動の大きさをそれぞれ0~1で指定します。両方とも0に設定すると振動が止まります。振動をオンにすると振動を続け、2秒後に止まるようになっています。多くの場合は自分で明示的に0にして止める必要があります。
周波数については変えても体感でほとんど分からないのですが、1よりも0のほうが心持ち荒い振動のような感じがします。
右手トリガーを引いている間振動を続けるサンプルスクリプトです。適当なGameObjectにアタッチしてください。
using UnityEngine;
public class ControllerVibrationTest : MonoBehaviour
{
void Update()
{
// 右手トリガーを引いたら振動を開始
if (OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger, OVRInput.Controller.RTouch))
{
OVRInput.SetControllerVibration(0f, 1f, OVRInput.Controller.RTouch);
}
// 右手トリガーを離したら振動を停止
if (OVRInput.GetUp(OVRInput.Button.PrimaryIndexTrigger, OVRInput.Controller.RTouch))
{
OVRInput.SetControllerVibration(0f, 0f, OVRInput.Controller.RTouch);
}
}
}
コントローラーでUGUIを操作するには
まず、Canvasで作成したUIをワールド空間に配置します(CanvasのRender ModeをWorld Spaceにして、Scaleを0.01等にして小さくします)。
CanvasにアタッチされているGraphics Raycasterの代わりにOVR Raycasterをアタッチし、Unity-StarterSamplesのAssets/StarterSamples/Core/DebugUI/PrefabsにあるUIHelpersプレハブをシーンにドロップするとコントローラーでポイントして操作できるようになります。
さらに、UIHelpersの中にあるLaserPointerオブジェクトのLine Rendererをオンにするとレイが表示されます。
ハンドトラッキングについて
ハンドトラッキングを使用するには
まずQuestの「設定 > デバイス > ジェスチャーコントロールとコントローラー」の「ジェスチャーコントロール」をオンにしてハンドトラッキングを有効にしてください。
Meta XR Core SDKパッケージのSamplesに入っているSample ScenesのHandTestシーンがハンドトラッキングの最小限のサンプルシーンなので、こちらを動かしてみるのが手っ取り早いです。シーンを開いたらOVRCameraRigを選択して、OVR ManagerのHand Tracking SupportをControllers And Handsに変更してビルドしてみてください。
OVRCameraRigのLeftHandAnchor / RightHandAnchorにOVRHandPrefabとOVRControllerPrefabがアタッチされていて、現在の入力に応じて手またはコントローラーが適宜表示されるようになっています。
エディタ上でハンドトラッキングを使用するには
Meta Horizon Linkを使用して、Unityのエディタ上でハンドトラッキングを使用できます。ビルドしなくても動作をテストできるため、ハンドトラッキングを使用したアプリの開発が楽になります。
Questの「設定 > デバイス > ジェスチャーコントロールとコントローラー」の「手とコントローラーの自動切り替え」をオンにした状態でMeta Horizon Linkを有効にしてください。このオプションがオフだと、ハンドトラッキングをオンにしていてもMeta Horizon Linkを接続した時点でオフに戻ってしまうのでエディタで手が使用できないようです。
Meta Horizon Linkでハンドトラッキングを使用するには
Meta Horizon Linkソフトウェアの ベータ > 開発者ランタイム機能 をオンにするとビルドしたWindows実行ファイルでもハンドトラッキングが使用できます。
ハンドトラッキングが効かないときは
手の位置が取れないとき→Project Settings > XR Plug-in Management > OpenXRのHand Tracking Subsystemがオンになっていますか?
手は動くがピンチ・ドラッグ操作が効かない→同じくXR Plug-in Management > OpenXRで、Enabled Interaction ProfilesにHand Interaction Profileが追加されていますか?
Meta Horizon Linkの場合、そもそもMeta Questのホーム画面でハンドトラッキングが動いていますか?(設定の問題や、Meta Questを再起動すると動くようになる場合があります)
手のマテリアルを変更するには
OVRHandPrefabを使用している場合、Skinnded Mesh RendererにBasicHandMaterialがアサインされているので、これを変更することで手のマテリアル・テクスチャを変更できます。
指でつまむ動作を取得するには
左右のOVRHandPrefabにアタッチされているOVRHandに対してGetFingerIsPinching(finger)を呼ぶと、それぞれの指先がほかのいずれかの指先とくっついているかどうかをtrue / falseで取得できます。
| 指 | fingerの値 |
|---|---|
| 親指 | OVRHand.HandFinger.Thumb |
| 人差し指 | OVRHand.HandFinger.Index |
| 中指 | OVRHand.HandFinger.Middle |
| 薬指 | OVRHand.HandFinger.Ring |
| 小指 | OVRHand.HandFinger.Pinky |
たとえば、親指と人差し指でつまむ形をしているかどうかは下記で判定できます。
public class FingerPinchTest : MonoBehaviour
{
[SerializeField]
OVRHand ovrHand;
void Update()
{
if (ovrHand.GetFingerIsPinching(OVRHand.HandFinger.Index) &&
ovrHand.GetFingerIsPinching(OVRHand.HandFinger.Thumb))
{
Debug.Log("つまんでる!");
}
}
}
親指と人差し指、親指と中指あたりでつまむ動作は比較的正しく取得できますが、3本以上になるとだいぶ怪しくなります。また、指先と指先がくっついているかの判定であって、指が立っているかどうかを判定するわけではないことに注意してください(たとえばグー・チョキ・パーの認識には使用できない)。
また、指先同士の接触の度合いを GetFingerPinchStrength で取得できます。指先と指先が離れていると0で、近づけると接触する数cmほど前から数値が上がっていき、接触する直前で1になります。
現在ハンドトラッキングかどうかを調べるには
OVRInput.IsControllerConnectedを使用すると、現在Touchコントローラーを使用しているか、ハンドトラッキングを使用しているかを調べることができます。
using UnityEngine;
public class ControllerChecker : MonoBehaviour
{
void Update()
{
var usingHand = OVRInput.IsControllerConnected(OVRInput.Controller.Hands);
var usingTouch = OVRInput.IsControllerConnected(OVRInput.Controller.Touch);
Debug.Log($"usingHand = {usingHand} / usingTouch = {usingTouch}");
}
}
なお、OVRInput.Controller.HandsとOVRInput.Controller.Touchは切り替わりの瞬間に両方ともfalseになっている場合があります。
ハンドトラッキングの精度を上げるには
Quest 2では設定により高頻度でハンドトラッキングができます。OVR ManagerのHand Tracking Frequencyで設定できます。
HIGHにするとデフォルトの30Hzではなく60Hzでトラッキングを行い、認識がよくなり低遅延になります。計算負荷によるオーバーヒートを避けるため、Hand Tracking FrequencyがLOWのときはCPUレベル3・GPUレベル3、HIGHのときはCPUレベル3・GPUレベル2までに制限されます。HIGHのときGPUレベル2までなのは結構厳しいので注意が必要です。「CPU・GPU レベルについて」を参照してください。
アイトラッキングを使用するには
アイトラッキングを使用するには、OVRCameraRigのOVR ManagerのGeneral > Eye Tracking SupportをRequiredに変更し、下のPermission Requests On Startupを開いてEye Trackingをオンにします。これにより、アプリ起動時に確認のメッセージが表示されるようになります。
手っ取り早い使い方としては、キャラクターの眼球に相当するオブジェクトにOVREyeGazeをアタッチして、EyeをそれぞれLeftとRightに設定、Apply Rotationをオンにして、Tracking ModeをHead Spaceにすると視線の向きにあわせて眼球のオブジェクトが回転します。
Meta Horizon Linkでアイトラッキングを使用したい場合は、Meta Horizon Linkアプリの「設定 > ベータ > 開発者ランタイム機能」をオンにして、その下の「Meta Horizon Link経由でのアイトラッキング」をオンにします。
Meta公式のサンプルおよび解説ページがあります。そこそこ重厚なサンプルで、動作させるにはレイヤー設定とプリロードシェーダーの設定(指示ダイアログが表示されます)、パッケージからProject内へのSceneのコピー等が必要です。
キーボードで文字を入力するには
アプリ内でQuestのキーボードを呼び出して文字入力に使用できます。
ProjectウィンドウのOculus/OculusProjectConfigでRequire System Keyboardを有効にすると、TouchScreenKeyboard.Openでキーボードが開きます(Quest実機のみ)。TouchScreenKeyboard.textで入力文字を取得できます。
また、Unity UI(uGUI)でInput Fieldをアクティブにしてもシステムキーボードが表示されます。注意点があり、Input FieldはTextMesh Pro版を使用しないと反応しません。また2024年5月現在、クリックしてもきちんと開かないことが多く、こちらのスレッドで、システムキーボードが開かなかった場合に強制的に開かせるhackが紹介されています。
Metaボタンを押したときの処理
アプリ実行中に右手コントローラーのMetaボタンを押してユニバーサルメニューを開くと、アプリは入力フォーカスを失います。この間もレンダリングを継続し、手やコントローラーのモデルを非表示にする(または両脇の待機姿勢にする)、手・コントローラー入力を無視する必要があります。ゲーム進行を一時停止するかどうかはアプリの設計次第です(VRC.Quest.Input.4)。
入力フォーカスを失うとOVRManager.InputFocusLostイベントが、復帰するとOVRManager.InputFocusAcquiredイベントがトリガーされます。
入力フォーカスを失っている間にゲーム進行も止めたい場合は、Time.timeScaleをゼロにする方法があります。
ヘッドセットをはずした・スリープした等を検知するには
ヘッドセットをはずすとOVRManager.HMDUnmountedイベントがトリガーされます。また、Quest本体のスリープと復帰でMonoBehaviour.OnApplicationPauseが呼び出されます。
その他、Questのアプリケーションライフサイクルで送られてくるイベントの一覧が下記ページにあります。
Questの機種を判定するには
OVRManager.systemHeadsetTypeで使用しているQuestの機種を取得できます。Quest 2、Quest Pro、Quest 3、Quest 3S等に対応する値は、使用中のMeta XR Core SDKのSystemHeadsetType列挙型を確認してください。
OVRManagerのTarget Devicesには、アプリが対応するすべての機種を設定します。新しい機種を判定できない場合は、Meta XR Core SDKとUnity OpenXR: Metaを互換性のある最新版へ更新し、Target Devicesを確認してください。
Meta Horizon Linkで接続している場合は、スタンドアロン実行時とは別のLink用の列挙値が返ります。機種の列挙を固定した分岐には必ず未知の値を扱うデフォルト処理を用意してください。
MRアプリを作るには
パススルー機能を使うには
Questアプリ内でヘッドセット外の光景を立体視で表示できます。Quest 2では低解像度のモノクロ表示、Quest Pro、Quest 3、Quest 3Sではフルカラー表示です。
以下のような表示をする最低限必要な方法を説明します。
まず、空のシーンを作成し、OVRCameraRigプレハブと、その前方に適当なオブジェクト(ここではキューブ)を配置します。
アプリのパススルー機能を有効にするために、OVR ManagerのPassthrough SupportをRequiredまたはSupportedにして、Meta > Tools > Android Manifest Toolでボタンを押します。Assets/Plugins/Android/AndroidManifest.xmlが更新され、以下の行が追加されます(Supportedだとrequiredがfalseに、Requiredだとtrueになります)。
<uses-feature android:name="com.oculus.feature.PASSTHROUGH" android:required="false" />
さらに、OVR Managerの下のほうにあるEnable Passthroughをオンにします。
パススルー映像の表示レイヤーを追加します。シーンにOVR Passthrough Layerコンポーネントを追加します。
URPではProject Settings… > Qualityで使用されているRender Pipeline AssetのHDRをオフにします(ビルトインでもオフにする必要があるかも)。
最後に、パススルー映像を消去してしまわないように、CenterEyeAnchorのカメラのClear Flags(URPならBackground Type)をSolid Colorに、Backgroundのカラーを(0, 0, 0, 0)に設定します。
Build and Runでアプリを実行すると、上のスクリーンショットのような表示ができているはずです。
なお、Quest 2では本体の撮影・録画機能でパススルー映像は記録されません。Quest 2でパススルー映像をキャプチャするには「動画をキャプチャするには」を参照してください。なお、Quest 3、Quest Proでは本体でパススルー映像を撮影・録画可能です。
Meta Horizon Linkでパススルー表示するには
WindowsのMeta Horizon Linkアプリの 設定 > ベータ > 開発者ランタイム機能 をオンにして、さらに下に出てくる「Meta Horizon Link経由でのパススルー」をオンにします。
上記の必要な設定をした上で、Unityでシーンを再生するとパススルー表示されます。Meta Horizon LinkアプリやUnityを再起動しないと有効にならないことがあるようです。
アプリ実行中にパススルー表示をオン・オフするには
OVR ManagerのPassthrough SupportをRequiredまたはSupportedにした上で、下記コードでEnable Passthroughを実行時に切り替えます。
OVRManager.instance.isInsightPassthroughEnabled = true;
起動時にパススルー表示したくない場合はあらかじめオフにしておきます。なお、シーンを切り替えるとこの設定はオフに戻るため、シーン遷移後に再度オンにする必要があります。
画面の一部をパススルー表示するには
TODO:今どこに入っているか確認
MixedReality/SelectivePassthroughシェーダーを使用します。SurfaceProjectedPassthrough、PassthroughHands等のサンプルがあります。
部屋と干渉するMRアプリを作るには
現在はMeta MR Utility Kit(MRUK)を使用するのが推奨です。MRUKはScene APIで取得した部屋・壁・床・家具等の情報を扱いやすくまとめ、プレハブ配置、コリジョン、レイキャスト、ワールドロック等の機能を提供します。
Package ManagerからMeta MR Utility Kitをインストールし、MRUKプレハブをシーンに配置します。シーンデータの読み込み完了後はMRUK.Instanceから現在の部屋やアンカーを取得できます。既存のOVRSceneManagerを使用しているプロジェクトは、OVRSceneManagerをMRUKプレハブに置き換えて移行します。
部屋の形状を取得するには
Questで設定したスペースの形状をMRUKから取得して、コリジョンや配置判定に使用できます。MRUKプレハブのScene Loaded Event、またはMRUK.Instance.SceneLoadedEventで読み込み完了を待ってから、MRUK.Instance.GetCurrentRoom()やMRUKRoom.Anchorsを参照します。
OVRManagerのScene SupportとPassthrough Supportを有効にし、Project Setup Toolで必要な権限とAndroidManifest.xmlの設定を確認してください。新規プロジェクトではOVRSceneManagerを使用しません。
現実空間の物体でUnityのオブジェクトを遮蔽するには
パススルーカメラから取得する物理空間の深度情報を利用して、バーチャルなオブジェクトと現実のオブジェクトの前後関係を表現できます。Unity 6、Meta XR SDK v74以降では、Unity OpenXR Pluginに加えてUnity OpenXR: Meta(com.unity.xr.meta-openxr 2.1.0以降)を使用します。以前のOculus XR PluginとGit URLからパッケージを追加する手順は旧バージョン向けです。
最も簡単な方法はBuilding BlocksからOcclusionブロックをシーンに追加することです。手動で設定する場合は、Meta XR Core SDKのEnvironmentDepthManagerコンポーネントをシーンに追加します。
Project Setup Toolで、次の要件をすべて修正してください。
- Graphics APIをVulkanにする
- Stereo Rendering ModeをMultiviewにする
- パススルーを有効にする
- OVRManagerのScene SupportをRequiredにする
- 起動時にScene権限を要求する
遮蔽されるオブジェクトには、Depth API対応シェーダーを使用したマテリアルが必要です。まずはビルトイン/URPの両方に対応するEnvironmentDepth/OcclusionLitを使用し、EnvironmentDepthManagerのOcclusion Shaders ModeでSoft OcclusionまたはHard Occlusionを選択します。
空間アンカーを使うには
空間アンカーは、セッションをまたいで保持できる物理空間上の位置です。パススルー機能と組み合わせることで、Mixed Realityのコンテンツを現実世界の同じ位置に復元できます。各アンカーにはUUID(UnityではSystem.Guid)が割り当てられ、作成、保存、読み込み、削除、共有ができます。
空間アンカーは正式機能になっており、Experimental設定やdebug.oculus.experimentalEnabledのシステムプロパティは必要ありません。OVRCameraRigのOVRManagerで Anchor Support を有効にします。アンカーを他のユーザーと共有する場合だけ Anchor Sharing Support も有効にしてください。
動作確認にはMeta XR Core SDKのStarter Samplesに含まれるSpatialAnchorシーンを使用できます。実装ではOVRSpatialAnchorコンポーネントをGameObjectに追加し、作成完了後にSaveAnchorAsync()で保存します。保存済みアンカーはUUIDを指定してLoadUnboundAnchorsAsync()で読み込み、ローカライズ後にGameObjectのOVRSpatialAnchorへバインドします。
永続化やユーザー間共有が不要で、単に現実空間へオブジェクトを固定したい場合は、MRUKのWorld Lockingを先に検討してください。
ビルドを速くするには
新しいバージョンのUnityを使用する
Unityは2020.3から2021.2にかけて多数のビルド・インポートの高速化が入ってきています。特にQuestで使用するIL2CPPやテクスチャのASTC圧縮が何倍も速くなっていますので、できるだけ早く2021.2以上に上げるのがおすすめです(現在、MetaのSDK自体もUnity 2021.3以降が必須要件になっています)。
Unity 2021.2ではBuild SettingsのIL2CPP Code GenerationをFaster (smaller) buildsにするとIL2CPPビルドがさらに倍速くなります。また、Project Settings > Editor > Parallel Importでテクスチャやモデルの並列インポートを有効にできます。
Monoビルドにする
Metaにアプリを提出する場合はIL2CPP/ARM64でビルドする必要がありますが、開発中はMono/ARMv7にするとビルドが速くてとても楽です。実行速度が遅くなるほか、カメラパススルー等、IL2CPPにしないと動かない機能があるため注意が必要です。
Skip Unneeded Shaders
Unityのモバイルビルドではグラフィックス性能によってTier 1からTier 3までの描画設定が切り替わるようになっていますが(Project Settings > Graphics を参照)、QuestではTier 2しか使用されません。Tier 2で使用されるシェーダーのみをビルドする設定を有効にするとビルド時間が短くなります。
Assets/Oculus/OculusProjectConfigを選択して、Build SettingsのSkip Unneeded Shadersをチェックしてください。
シェーダーストリッピングの処理は OVRShaderBuildProcessor.cs で行われています。
Unity Acceleratorを使用する
アセットの変換をキャッシュするUnity Acceleratorを使用することで、同じアセットを繰り返しインポートするときに変換処理を走らせなくて済むようになります。下記ページを参照してください。
USB 3.0ケーブルを使う
USB 3.0ケーブルを使うとビルドしたapkファイルのQuestへの転送時間が短くなります。下記エントリが参考になります。
OVR Scene Quick Preview
Oculus Integrationに含まれているツールで、Questでアプリを起動したままでシーンを更新できるツールです(Asset Bundleを使用しています)。簡単な実験シーンを更新して試したり、負荷を比較したりするのに使用できます。
使用方法は以下の通りです。
- あらかじめBuild Settingsでシーンを登録しておく
- Oculus > OVR Build > OVR Scene Quick Previewメニューでウィンドウを開く
- 「Build and Deploy App」で転送用のアプリをビルド・起動する
- 「Build and Deploy Scene(s)」を押すとQuestのシーンが更新される
OVR Build APK and Run
Oculus > OVR Build > OVR Build APK and Runでビルドすると、ビルドの最終段の “Building Gradle project” がキャッシュされます。ビルド時間が数割短縮されます。
このメニューはUnityのプラットフォームをAndroidにしないと表示されないので注意してください。また、Android Logcatを使用している場合は、実行開始時にフィルターが自動で設定されないため自分で設定する必要があります。
パフォーマンス最適化
フレームレートの維持の必要性
Meta Horizon Storeへ提出するアプリは、VRC.Quest.Performance.1により、原則として60fps以上のレンダリングレートを維持する必要があります。インタラクティブアプリで使用できるリフレッシュレートは72Hz、80Hz、90Hz、96Hz、100Hz、120Hzです(機種やHorizon OSのバージョンによって使用できない値があります)。
ローディング画面や全面フェード中、ストリーミング・録画中には例外があります。Application SpaceWarpを使用している部分は、適切なモーションベクターを生成することを条件に、リフレッシュレートの半分のレンダリングレートが許可されます。
CPUとGPUの1フレームあたりの処理時間は、60fpsなら16.67ミリ秒、72fpsなら13.89ミリ秒、90fpsなら11.11ミリ秒以内に収める必要があります。Questはモバイル機ですので、対象機種と設定したリフレッシュレートの組み合わせごとに実機で確認してください。
QuestのCPU・GPUについて
Questの機種ごとの搭載SoCは以下の通りです。
| 機種 | SoC |
|---|---|
| Meta Quest 3 | Snapdragon XR2 Gen 2 |
| Meta Quest 3S | Snapdragon XR2 Gen 2 |
| Meta Quest Pro | Snapdragon XR2+ |
| Meta Quest 2 | Snapdragon XR2 |
| Meta Quest | Snapdragon 835 |
Meta公式ブログの下記エントリにMeta Quest 1のハードウェア詳細の解説があります。
Quest 1はSnapdragon 835を搭載しています。CPUは8コアで、4つが性能重視の Performanceコア(Cortex-A73)、4つが省電力重視の Efficiency コア(Cortex-A53)です。アプリの実行に割り当てられているのは3つのPerformanceコアで、残りの1つのPerformanceコアはタイムワープとシステムサービスに、4つのEfficiency コアはトラッキングやその他のシステムソフトウェアに使用されているとのことです。
GPUはSnapdragon 835に統合されているAdreno 540です。多くのモバイルGPU同様タイルベースレンダリングであることに注意が必要です。
CPU・GPUレベルについて
QuestのCPU・GPUは、バッテリー消費を抑えつつフレームレートを維持するために、CPU・GPUレベルという形でクロック周波数が変動します。現在のレベルおよびクロック周波数はOVR Metrics Toolを使うとヘッドセット内で確認できます(CPU L/CPU FとGPU L/GPU F)。
最低レベルを下記APIで設定できます。たとえばCPUをSustainedLowに設定すると、通常時がレベル2で、負荷が増えて処理オーバーしそうになるとレベル3、4と上がっていき、処理に余裕ができるとゆっくりと2に戻っていきます。
OVRManager.suggestedCpuPerfLevel = OVRManager.ProcessorPerformanceLevel.SustainedLow;
OVRManager.suggestedGpuPerfLevel = OVRManager.ProcessorPerformanceLevel.SustainedHigh;
以下は参考までに、Quest 2で空シーンでCPUとGPUのレベル設定を切り替えたときのOVR Metrics Toolのプロセッサーレベルと周波数の表示です。
| suggestedCpuPerfLevel | CPU L | CPU F |
|---|---|---|
| PowerSavings | 0 | 710 |
| SustainedLow | 2 | 1171 |
| SustainedHigh | 3 | 1382 |
| Boost | 4 | 1489 |
| suggestedGpuPerfLevel | GPU L | GPU F |
|---|---|---|
| PowerSavings | 0 | 305 |
| SustainedLow | 1 | 400 |
| SustainedHigh | 2 | 441 |
| Boost | 3 | 490 |
できるだけ低いレベルで目標のフレームレートを維持できるようにしておくのが好ましいですが、低いレベルに設定していると突然負荷がかかったときにフレーム落ちする場合があります。このあと負荷がかかる処理が来ると分かっているようなときに、あらかじめレベルを上げておくことができます。
注意が必要なのがパフォーマンスを計測するときで、レベルによってCPU・GPUの使用率の数値が変動します。使用率を比較する場合は明示的にレベル設定をして、同じレベルで比較する必要があります。
パフォーマンス最適化に使用できるツール
Questのパフォーマンス最適化に使用できるツールはMeta、Unity、Google、Qualcommから提供されているものやオープンソースのツール等多岐に渡ります。どれを使えばいいか迷ってしまいますが、うち特に効果的なものをいくつか紹介します。
OVR Metrics Tool
真っ先に使用するべきツールがこれになります。フレームレートやQuestの各種メトリクスをヘッドセット内でオーバーレイ表示できます。アプリがどんなシチュエーションで重くなるかをヘッドセットをかぶったままで簡易的に確認できます。
OVR Metrics ToolはMeta Horizon Storeからインストールできます。起動すると設定画面が出てくるので、「Enable Persistent Overlay」を有効にすると常時表示された状態になります(表示されなくなったときは電源ボタンで一度スリープして復帰してみてください)。
まずは設定画面の真ん中にあるプリセットの「BASIC」ボタンあたりをクリックしてください。また、デフォルトでは表示位置が上すぎると思いますので、Pitchを調整してみてください。
STATSタブで表示項目をひとつひとつオン・オフできます。多数の項目がありますが、特に表示しておきたい項目を下記に列挙します。
| 項目 | 表示 | 説明 |
|---|---|---|
| Average FPS | FPS | 平均フレームレート |
| CPU Level | CPU L | 現在のCPUレベル(0-4) |
| GPU Level | GPU L | 現在のGPUレベル(0-4) |
| GPU Utilization | GPU U | GPU使用率(0-100) |
| Stale Frame Count | STALE | フレーム落ちした数 |
| Foveation Level | FOV | 現在のFoveated Renderingのレベル(0-4) |
CPU使用率について、STATSの下のほうにある「CPU Utilization (Core 0-7)」を有効にするとコアごとの数値を表示できます。Core 0-3がPerformanceコア、4-7がEfficiencyコアのようです。
また、adb shell ovrgpuprofiler -eを実行するとGPUの細かい項目も有効にできるようになります。無効に戻すには-dオプションです。
OVR Metrics Toolのドキュメントは下記ページにあります。
Unity のプロファイラー
Unityのプロファイラーを使用するとQuest実機の処理内容と実行時間を確認できます。Build SettingsでDevelopment Buildを有効にした上でビルド・実行して、Windows > Analysis > Profilerでプロファイラーを開き、上部のPlay Modeと表示されているところでQuestを選択してください。
CPU Usageの列が約13.888…ミリ秒(72fpsの場合)で安定し綺麗な長方形になっているのがCPUまたはGPUの処理オーバーが起きていない正常な状態です。また、画像のようにTimeline表示にしてQuestの1フレームのCPUの実行処理の詳細を調べられます。
RenderDoc
RenderDocはオープンソースのフレームデバッガで、各種グラフィックスAPIで描画コールの実行をトレースしたり、おおまかな実行時間を計測表示できます。
Quest用に機能が追加されたRenderDoc Meta Forkがあり、Meta Quest Developer Hubからインストールできます(Windows 専用)。Questの各種メトリクスを表示できるようになっています。
- RenderDoc
- Optimize Your Graphics with RenderDoc Meta Fork
- Use RenderDoc Meta Fork for GPU Profiling
- Draw Call Metrics
Oculus のブログに使い方が詳しいです。描画コールごとの実行時間が計測表示できますが、タイルベースレンダリングなので参考程度にとのことです。
- How to Optimize your Oculus Quest App w/ RenderDoc: Getting Started + Frame Capture
- Use RenderDoc Meta Fork for GPU Profiling
実行時間を確認するときのおおまかな使い方のメモです。
- プロジェクトの Build Settings の Development Build をオンにして Build And Run
- RenderDoc for Oculus を起動
- 左下の Replay Context を Oculus Quest 2 に変更して接続を待つ
- 真ん中の Launch Application タブの Executable Path で該当アプリのパッケージ名を com.unity3d.player.UnityActivity を選択して OK ボタン
- 右下の Launch ボタンを押してアプリを起動
- 右の Capture Frame(s) Immediately ボタンを押すとフレームがキャプチャされる
- 保存されたフレームをダブルクリックすると描画コールの一覧が出てくる
- Event Browser の時計のアイコンをクリックすると描画コールごとのおよその実行時間が出てくる
Perfetto
さらに詳しくQuest実機のパフォーマンス状況を追いかけたいときは、Google製のPerfettoというツールがあります。Meta Quest Developer Hubに統合されており、Performance Analyzerタブで表示できます。
Snapdragon Profiler
Qualcomm の公式ツールです(Qualcomm の開発者アカウント作成が必要)。Snapdragon の各種メトリクスを詳細表示できます。Snapdragon の CPU 各コアごとの使用率や、タイルベースレンダリングのタイル数等を確認できます。通常は上記のツールで十分なので、使用する機会は少ないかもしれません。
その他の参考になる情報
コアな情報として、Meta公式ブログの下記エントリにQuestのレンダリングパイプラインの解説があります。
モバイルGPUで使用されているタイルベースレンダリングについて簡潔に説明されているページです。
下記エントリにOpenGLとVulkanでのタイルベースレンダリングの動作についての解説があります。
QualcommのサイトにSnapdragonのゲーム開発者向けガイドがあり、左のタブのAdreno GPUのところにベストプラクティスが掲載されています。シェーダーの最適化Tipsなどが載っています。
下記はUnityではなくUE4のスライドですが、考え方は一緒ですので参考になります。
描画解像度について
VRヘッドセットはディスプレイの解像度およびリフレッシュレートが高く、ピクセルの描画がGPUの大きな負荷になります。Standard Shaderやユニティちゃんトゥーンシェーダー等、フラグメントシェーダーが重いマテリアルで視野の広範囲が覆われている場合、描画解像度を調整することで、見た目をあまり損なわずにGPUの計算量を下げられる場合があります。
UnityでQuestアプリをビルドしたときのデフォルトのアイバッファ解像度は、Questのディスプレイ解像度より若干低めになっています(OVR Metrics Toolの「EB W」「EB H」表示で確認できます)。一方、Meta Horizon Linkで接続するとディスプレイ解像度に近いアイバッファ解像度になります。このため、デフォルトではMeta Horizon Linkよりもアプリ実行時のほうが少しぼやけて見えます。
周辺視野の解像度の変更
Fixed Foveated Rendering
目立たない周辺視野の描画解像度を下げることによってGPU負荷を下げるVR特有の最適化機能です。ケースによりますが、GPU使用率が10%から数十%下がります。
下記APIで使用できます。
// Off、Low、Medium、High、HighTopのいずれかを設定
OVRManager.foveatedRenderingLevel = OVRManager.FoveatedRenderingLevel.High;
現在のレベルは、OVR Metrics ToolのSTATSでFoveation Levelの項目をオンにするか、Android Logcatの下記表示のFovのところを見ると確認できます。
FPS=72/72,Prd=39ms,Tear=0,Early=0,Stale=0,Stale2/5/10/max=0/0/0/0,VSnc=0,Lat=-3,Fov=0,CPU4/GPU=4/3,...
Foveated Renderingの仕組みとしては、タイルベースレンダリングのタイルごとに解像度を変えているようです。詳細の解説がこちらにあります。
なお、URPでもFoveated Renderingは使用できますが、Custom Render Featureと併用できない制限があります。設定を有効にすとOVR Metrics Toolの表示は変わるのですが、描画に反映されずGPU使用率も減りません(URP 13で対処されている?)。
Dynamic Foveated Rendering
描画負荷によって自動的にFoveated Renderingのレベルを変動させます。通常はオフの状態で、負荷が増えてフレーム落ちしそうになるとレベルが徐々にfoveatedRenderingLevelで指定したレベルまで上がっていき、負荷が減ると徐々にレベルが下がってオフに戻っていきます。
OVRManager.useDynamicFoveatedRendering = true;
OVRManager.foveatedRenderingLevel = OVRManager.FoveatedRenderingLevel.High;
adbコマンドで一時的に設定を変更する
下記adbコマンドで、アプリの外からFoveated Renderingの設定を変更できます。パフォーマンス検証に使用できます。Questを再起動するとリセットされます。
$ adb shell setprop debug.oculus.foveation.level 0 (0~4)
$ adb shell setprop debug.oculus.foveation.dynamic 0 (0:オフ/1:オン)
視野全体の解像度の変更
下記APIで視野全体の描画解像度を変更できます。0.9等に試しに下げてみるのがおすすめです。
using UnityEngine.XR;
...
XRSettings.eyeTextureResolutionScale = 0.5f;
現在の描画解像度は、OVR Metrics ToolのSTATSでEye Buffer Width(EB W)とEye Buffer Height(EB H)の項目を表示すると確認できます。
URPを使用している場合は、Universal Render Pipeline AssetのRender Scaleでも変更できます。
テクスチャを綺麗に表示するには
テクスチャの描画品質を上げたい場合、こちらのエントリが非常に詳しく必読です。
圧縮フォーマットをASTCにする
Questのテクスチャ圧縮フォーマットは基本的にASTCにします(ただし、Project Setup ToolではデフォルトでETCに設定されるようです)。
Build SettingsでデフォルトのTexture CompressionをASTCにして、個々のテクスチャで調整が必要な場合はFormatでRGB(A) Compressed ASTCの4x4 blockから12x12 blockまでを選択します。ブロックサイズを大きくすると圧縮率が上がります(Applyしてインスペクター最下部のテクスチャ容量の数値が変わるのを確認してください)。
ミップマップを適切に設定する
VRではテクスチャに近づいたり離れたりすることが非常に多いです。距離に応じて適切な解像度で描画されるように、テクスチャのインポート設定でGenerate Mip Mapsをオンにします。
また、距離によってミップマップのポッピング(急な切り替わり)が起きないようにするにはFilter ModeをTrilinearに変更します。そこそこ負荷が増えるようです。
異方性フィルタリングを有効にする
地面や壁など斜めの角度から見ることが多いテクスチャは、インポート設定でAniso Levelを上げると綺麗に表示されます。
リフレッシュレートについて
リフレッシュレートを設定するには
使用できるリフレッシュレートは機種とHorizon OSによって異なります。固定の機種表に依存せず、OVRManager.display.displayFrequenciesAvailableで実行中の端末が対応する値を取得してから、OVRManager.display.displayFrequencyへ設定します。
たとえば90Hzに対応している場合は下記で設定できます。
OVRManager.display.displayFrequency = 90f;
対応しているリフレッシュレートの一覧はOVRManager.display.displayFrequenciesAvailableで取得できます。以下の要領で確認できます。
using System.Linq;
...
if (OVRManager.display.displayFrequenciesAvailable.Contains(90f))
{
OVRManager.display.displayFrequency = 90f;
}
現在のリフレッシュレートは、Android Logcatで毎秒出力されるログ表示や、OVR Metrics Toolの表示で確認できます。
リフレッシュレートを取得するには
OVRManager.display.displayFrequencyで現在のリフレッシュレートを取得できます。displayFrequencyに値を代入して実際にリフレッシュレートが変更されるまでは値が反映されていないため注意してください。
リフレッシュレートが変わるとOVRManager.DisplayRefreshRateChangedイベントが飛んできます。
Application SpaceWarpについて
Application SpaceWarpは、(上手くいけば)見た目をあまり損なわずにフレームレートを倍にできる最適化機能です。Unityでたとえば36fpsの映像フレームを生成すると、Questのコンポジターが中間フレームを補間して72fpsの映像を生成します。半分のフレームレートでレンダリングすればいいので、CPUとGPUの負荷が半分近く減少します。
Application SpaceWarpにはURPが必要で、フレーム内のピクセルの移動方向を格納した特殊な(Unity標準のものとは異なる)モーションベクターバッファを描画する必要があります。独自のシェーダーでApplication SpaceWarpの恩恵を得るには、シェーダーにモーションベクターバッファの描画パスを追加する必要があります。
フレームレートが下がる結果コントローラーの入力遅延は大きくなったり、描画内容(HUDやメッシュアニメーション、パーティクル等)によってはフレーム補間がまったく効かなかったりするので、導入にあたってはトレードオフの検討が必要です。
使用するには、Graphics APIをVulkanだけにし、Project Settings > XR Plug-in Management > OpenXR > All FeaturesでMeta XR Space Warpを有効にします。Unity 6では標準URPにも対応がありますが、追加の最適化や半透明対応を含むMeta管理のURPフォークが引き続き推奨されています。UnityとURPのバージョンごとに使用するブランチが異なるため、Application SpaceWarp Developer Guideで対応表を確認してください。実行中のオン・オフにはMeta XR Core SDKのOVRManager.SetSpaceWarpを使用します。
Application SpaceWarpのサンプルを動かす
GitHubにApplication SpaceWarp対応のScriptable Render Pipelineリポジトリがあります。Unityの各バージョンに対応したoculus-app-spacewarpという名前のブランチがありますので、必要なバージョンを調べてcloneします。
git clone -b 2021.3/oculus-app-spacewarp https://github.com/Oculus-VR/Unity-Graphics/
TestProjects/OculusAppSpaceWarpSimpleフォルダ(2022.3ブランチはOculusAppSpaceWarpSampleフォルダ)にUnityのプロジェクトがあるので、Androidプラットフォームで開きます。プロジェクトがUnity 5.0より前のような警告ダイアログが出てくるかもしれませんが無視します。
Meta XR Core SDKをインポート、Assets/ScenePackage.unitypackageをダブルクリックしてScenePackage/SpaceWarpScene.unityを開きます。
ビルドしてBボタンでApplication SpaceWarpをオン・オフします。有効になっていれば、Android Logcatの毎秒の出力にASWの項目が出てきます。また、OVR Metrics ToolのASW FPSの項目がゼロから変動します。たとえばリフレッシュレート72HzでApplication SpaceWarpが効いていればFPS: 36、ASW FPS: 72と表示されます。
Application SpaceWarpの仕組み
フレームを補間するために、アプリケーションはシェーダーに追加されたMotionVectorsパスを使用して低解像度(Quest 2では368x400)のモーションベクターバッファを生成します。バッファはOpenXRのXR_FB_space_warp拡張を通してコンポジターにサブミットされます。
モーションベクターバッファには、各ピクセルの前のフレームと現在のフレームのNDC(正規化デバイス座標)の差が3Dベクトルで入ります。ピクセル深度も格納されます。
コンポジターは、モーションベクターバッファを利用してフレームの各ピクセルが次のフレームのどこにあるかを推測します。また、Questの通常のTimeWarpではカメラの回転しか補正しませんが、Application SpaceWarpではモーションベクターバッファに格納されたピクセルの深度によりカメラの移動についても補正します(Positional TimeWarp)。
なお、Unityの標準機能にもモーションベクターバッファがありますが、負荷低減のために低解像度のバッファを生成するのと、深度バッファを生成するために専用のモーションベクターパスが使用されています。
このコミットがシェーダーで専用のモーションベクターバッファを描画するための主要な変更箇所として紹介されています。とりわけ、OculusMotionVectorCore.hlslの下記フラグメントシェーダーが根幹部分になります。
half4 frag(Varyings i) : SV_Target
{
float3 screenPos = i.curPositionCS.xyz / i.curPositionCS.w;
float3 screenPosPrev = i.prevPositionCS.xyz / i.prevPositionCS.w;
half4 color = (1);
color.xyz = screenPos - screenPosPrev;
return color;
}
Application SpaceWarpの弱点
上記の原理上、描画内容によってはフレーム補間が上手くいきません。下記リポジトリのREADMEにApplication SpaceWarpによって発生する典型的なアーティファクトのサンプル動画があります。
UIの描画
ゲームのUIやHUDをオーバーレイ表示すると、モーションベクターバッファにより振動が発生します(動いていないHUDが中間フレームで動いているように移動させられてしまう)。Application SpaceWarpの影響を受けないOVROverlayで描画するか、3D空間内にUIを配置する必要があります。
半透明レンダリング
モーションベクターバッファには重なっている2つ以上のピクセルの動きを格納できないため、半透明に弱いです。遠方のオブジェクトやアニメーションが速いエフェクト等は問題ないものの、近距離を高速で動くオブジェクトは要注意です。たとえばバーチャルなコントローラーに透過するメニューパネルがついていたりするとまずそうです。
その他
高速回転するオブジェクト、複雑な頂点アニメーション、人工的なテクスチャパターン等に弱いです。また、パーティクルエフェクトなどはそもそもフレーム補間されようがないので半分のフレームレートで描画されてしまいます。
これらについて、描画の仕方を変える、モーションベクターバッファの描き方を変える、状況に応じてApplication SpaceWarpをオフにする等の対策を考える必要があります。
フェードイン・フェードアウトするには
OVRScreenFadeを使う
OVRScreenFadeをCenterEyeAnchorにアタッチするとシーン開始時にフェードインします。目の前に半透明ポリゴンを描いて覆う仕組みになっています。
フェードアウトするにはFadeOutメソッド、フェードインするにはFadeInメソッドを呼びます。
OVRManager.SetColorScaleAndOffsetを使う
別の方法としては、OVRManagerの関数でヘッドセット内の画面全体のピクセルの色にフィルターをかけられます。Questで効くのは第1引数のカラースケールだけで、カラーオフセットは効かないようです(ただしOpenXRのプラグインを使用している場合はカラーオフセットが使えるようです)。
OVRManager.SetColorScaleAndOffset(Vector4 colorScale, Vector4 colorOffset, bool applyToAllLayers)
DOTweenとSetColorScaleAndOffsetを使用してフェードイン・フェードアウトするサンプルクラスです。
using DG.Tweening;
using UnityEngine;
public class Fader : MonoBehaviour
{
Color filterColor;
void Update()
{
if (OVRInput.GetDown(OVRInput.RawButton.A))
{
FadeTo(Color.white, 1f);
}
if (OVRInput.GetDown(OVRInput.RawButton.B))
{
FadeTo(Color.black, 1f);
}
}
public void FadeTo(Color color, float durationSec)
{
DOTween.To(() => filterColor, c => filterColor = c, color, durationSec)
.SetEase(Ease.Linear)
.OnUpdate(() => OVRManager.SetColorScaleAndOffset(filterColor, Color.clear, true));
}
}
3Dサウンドを使用するには
Meta XR Audio SDKパッケージに3D空間音響のプラグインが含まれており、QuestとPC両方で動作します。
Unityのデフォルトのステレオサウンドでは、AudioSourceを3Dにしても左右の音量バランスが変わるだけで、左右どちらから音が鳴っているかしか分かりませんが、Meta XR Audio SDKを使用すると、HRTF(頭部伝達関数)を用いて耳に入ってくる音にフィルタをかけることで、シーン内の音源に立体的な定位感が与えられます。個人差がありますが、前で鳴っている音と後ろで鳴っている音の判別ができるようになり、上方向・下方向から鳴っている音がそれらしく聴こえるようになります。特にVRにおいては頭の向きを変えると音源の方向が変わるため、自分が実際にその空間にいるかのような臨場感が増強されます。
また、音が部屋の壁で跳ね返ることによる残響音(初期反射音およびリバーブ)や、Near-field Rendering(距離1メートル未満の音源について音波の回折効果でリアルな表現にする)の効果も実装されています(技術的な解説ページ)。
セットアップ方法
Meta XR Audio SDKをインポートすると、Project Settings > AudioのSpatializer PluginとAmbisonic Decoder PluginにMeta XR Audioが設定されます。必要に応じてDSP Buffer Sizeを調整します(Best latencyにするといいとのことです)。
プロジェクト内にAssets/Resources/MetaXRAudioSettingsが作成され、Voice Limit(同時発音数)の設定があるのでパフォーマンス次第で調整します。
パッケージのSamplesからExample Scenesがインストールできます。なおサンプルシーンはどれもVRモードではなく、WASDキー+マウスで移動するようになっています。
音の定位感を得るには
Audio SourceのついたオブジェクトにMeta XR Audio Sourceコンポーネントを追加することで3Dサウンドの効果が有効になります。3Dサウンドに使用できる音源はモノラル音源のみです。Reverb Send Dbを上げるとリバーブがかかります。
さらにMeta XR Audio Source Experimental Featuresコンポーネントを追加すると以下の設定ができるようになります。
Volumetric Radius
音源の大きさを設定します。技術的な解説ページがあります。
Directivity Intensity / Directivity Pattern
音に指向性を持たせます。人の話し声であればDirectivity PatternをHuman Voiceに変更するとよさそうです。Example Scenesに含まれているSourceDirectivelyシーンでは3人の指向性のある声による会話が聞こえてくるのですが、だいぶ効果的で、ちょっとびっくりするのでおすすめです。
音の向きを変えるにはゲームオブジェクトを回転させればオーケーです。
Hrtf Intensity
HRTFのかかり具合を調整します。クリエイティブな理由で気になったら下げるようにとのことです。
空間の残響音を得るには
部屋の形状をシミュレートして初期反射音とリバーブ(残響音)の効果を追加できます。Example Scenesに含まれているRoomAcousticsシーンがサンプルシーンになります。
必要な設定としては、Audio MixerにMeta XR Audio Reflectionを挿して、Meta XR Audio Room Acoustic Propertiesコンポーネントがついたオブジェクトを配置し、このコンポーネントで部屋のサイズとそれぞれの壁の材質を設定します。複数の部屋を移動したい場合はプロパティを更新すると反映されます。
Ambisonicsを再生するには
360度音響のAmbisonicsの音源を再生できます(一次AmbisonicesのAmbiXファイル)。再生するにはProject Settings > AudioのAmbisonic Decoder PluginにMeta XR Audioが設定されていることを確認した上で、AudioSourceのAudioClipに設定するだけです。AudioSourceまたはAudioListenerのゲームオブジェクトを回転すると音源が回転します。
Example ScenesにサンプルのAmbisonicsシーンが含まれています。
アプリをリリースするには
Questのアプリ配布手段について
Meta Horizon Store
2024年7月31日以降、Questの一般公開アプリはすべてMeta Horizon Storeへ提出します。
Meta Horizon Developer Dashboardでアプリを作成し、ビルド、商品ページのテキストや画像、年齢区分、プライバシーポリシー等を登録してProductionリリースチャンネルから審査へ提出します。アプリはVirtual Reality Check(VRC)とStore Review Policiesを満たす必要があります。
Release Channels
開発中のビルドやクローズドテストには、ALPHA、BETA、RC等のRelease Channelを使用します。Productionは一般公開の審査に提出するビルド専用です。各チャンネルへテストユーザーを追加または招待し、限定配布できます。
apkファイルの直接配布
Metaのプラットフォーム外でapkファイルを直接配布する方法をサイドローディングといいます。ユーザーはMeta Horizonアプリの設定で「提供元不明」を有効にしてインストールします。サイドロードしたアプリはMetaから自動更新されず、Horizonの機能やサービスも利用できません。SDKライセンスやPlatform Abuse Policy等には引き続き従う必要があります。
SideQuest
サイドローディングのアプリを配布する非公式のアプリポータルとしてSideQuestがあります。PCにポータルソフトウェアをインストールして、Questにapkファイルをインストールできます。インディーゲーム販売サイトitch.ioの決済システムを利用して有料apkファイルの配布も活発に行われています。
Meta Quest Browser (WebXR)
ネイティブアプリではなく、Questのウェブブラウザ(Meta Quest Browser)で動くウェブアプリとして開発することも考えられます。Meta Quest BrowserはChromiumベースのブラウザで、WebXRサポートが積極的です。ハンドトラッキングのAPIにも対応しています。
WebXRアプリを作るには、JavaScriptでThree.jsやA-Frame、Babylon.js等のWebGLライブラリを使用するほか、UnityでもWebXR Exportを使用するとWebGLビルドをWebXRに対応させられます。詳しくは「Unity + WebXR開発メモ」を参照してください。
アプリ提出時のTips
Meta Horizon Storeへアプリを提出する際にチェックが必要なポイントについてまとめます。
ガイドラインに目を通す
Meta Quest Virtual Reality Check (VRC) Guidelines というガイドラインがあり、アプリが各項目に準拠しているか審査されるため要チェックです。フレームレートの確保、不要なマイク権限の削除、Metaボタンを押したときの処理あたりがおそらく引っかかりやすいポイントだと思います。
Android API Levelを設定する
Project Settings > Player > Other Settingsで、Minimum API LevelをAndroid 10(API Level 29)以上、Target API LevelをAutomatic (highest installed)に設定します。特定の古いAPI Levelへ固定せず、Project Setup Toolと公開準備の公式ページで現在の要件を確認してください。
パッケージ名を適切につける
QuestアプリはUnityのProject SettingsのPlayer > Package Nameをもとに識別されます(つまり、Package Nameを変えると別のアプリとして認識されます)。
Metaのダッシュボードにアップロードするapkファイルをビルドする際に適切なパッケージ名を設定しておきます。通例、ドメイン名を逆順にした「com.[会社名].[プロダクト名]」のような名前をつけます。
App IDの設定
Meta XR Platform SDKの機能を使用する場合はApp IDを設定します。Developer Dashboardでアプリを作成し、Development > APIからApp IDを取得します。Unityで Meta > Platform > Edit Settings を開き、対象プラットフォームのApplication IDへ貼り付けます。
アプリへの署名
apkファイルをビルドする際に署名が必要です。Project SettingsのPlayer > Publishing Settings > Keystore Manager…で署名ファイル(*.keystore)を作成して署名します。アプリのアップデートの際は同じ署名ファイルで署名する必要があります。設定したパスワードを忘れないように注意してください。プロジェクトファイルには保存されません。
詳しくはAndroidのkeystoreについて検索してみてください。
Bundle Version Codeの設定
MetaのダッシュボードはProject SettingsのPlayer > Other Settings > Bundle Version Codeの数値でアプリのバージョンを識別しています。新しいバージョンのapkファイルをアップロードするたびにBundle Version Codeの数値を増やしてビルドする必要があります。
Entitlement Check
apkファイルをMeta Horizon Store経由でダウンロードしたときにのみ動くようにすることができます(VRC.Quest.Security.1)。
Meta XR Core SDKとMeta XR Platform SDKをインストールし、App IDを設定してから、Platform SDK entitlementsの現行手順に従って実装・テストします。Oculus Integration時代のOculus/Platform/Samples/EntitlementCheckを前提にしないでください。
不要な権限を要求しないようにする
apkファイルには必要最小限の権限を与える必要があります(VRC.Quest.Security.2)。不要な権限が付与されているとエラーでダッシュボードにアップロードできません。
apkファイルの使用権限を確認するには
aaptというツールを使うと以下のようにapkファイルの要求権限を確認できます。
> aapt dump permissions Example.apk
package: com.framesynthesis.XRSynthesis.development
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
uses-permission: name='android.permission.RECORD_AUDIO'
uses-permission: name='android.permission.MODIFY_AUDIO_SETTINGS'
uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE'
uses-permission: name='android.permission.READ_PHONE_STATE'
uses-permission: name='android.permission.READ_EXTERNAL_STORAGE'
aapt.exeはUnityをインストールすると以下のフォルダにインストールされています。
C:\Program Files\Unity\Hub\Editor\{Unityのバージョン}\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\{バージョン番号}\aapt.exe
マイク権限の注意
マイクを使用しないアプリなのにマイク権限があると審査でリジェクトされます。過去にあったトラップとして、Oculus Integrationをインポートすると、Oculus/LipSyncやOculus/AvatarによってUnityがビルド後のAndroidManifest.xmlにRECORD_AUDIO等のパーミッションを自動的に付与してしまうということがありました。
マルチプレイヤーアプリの注意
マルチプレイヤーのゲーム等でMetaボタンから不適切なコンテンツやユーザーを通報できるようにする必要があります。User Reporting Pluginを使ってレポート機能を起動できるようにするか、2023 Q1からダッシュボードで提供されるUser Reporting Serviceを使用とのことです。
ダッシュボードにアプリをアップロードする
上記設定を行ってビルドしたapkファイルをMeta Quest Developer Hubにドラッグすると、ダッシュボードにアップロードするためのダイアログが表示されます。
または、Metaが提供するコマンドラインツールを使用してアップロードすることもできます。ビルドスクリプトやCIに組み込んでおくと便利です。
ダッシュボードから取得したApp IDとApp Secretを使用して、
ovr-platform-util.exe upload-quest-build --app-id [App ID] --app_secret [App Secret] --apk Build.apk --channel alpha
のようにしてアップロードします。
個人情報の取り扱いについて
プライバシーポリシーを作成してURLでアクセスできるようにしておく必要があります。
また、Metaのプラットフォーム機能を使用するには、個人情報を適切に扱っていることを確認するデータ保護評価(Data Use Checkup)という手続きに従う必要があります。1年に一度再認定を受ける必要があり、従わないとアプリのプラットフォーム機能が無効化されたり、ストアから削除されたりする可能性があります。有効期限が切れる数週間前にMetaからメールで通知が届きますのでよく確認しておきましょう。
アプリを他のユーザーに共有するには
ダッシュボードにアップロードしたアプリを、Release Channel経由で他のユーザーにインストールしてテストしてもらうことができます。各チャンネルはデフォルトで200人まで、Channel Settingsで2,500人まで拡張できます。上限を拡張する場合はData Use Checkupの審査等が必要になることがあります。
ダッシュボードの左列の「リリースチャンネル(Release Channels)」をクリックし、該当チャンネルをクリックして「チャネル設定(Channel Settings)」の「URLによるユーザーへのアクセス付与(Grant access to users by URL)」で招待用のURLを発行できます。
URLを受け取ったユーザーは、Metaアカウントにログインした上でURLのアプリのページを開いて、「Join」ボタンをクリックして少々待つとデバイスのアプリページに表示されインストールできるようになります。
境界線について
境界線はどれくらいの大きさまで引けるの?
Roomscaleの境界線は最大で約7×7メートルです。安全性と安定性のため、Metaは約2×2メートルのプレイエリアを推奨しています。Stationaryではユーザーを中心に約1×1メートルの境界線が設定されます。
境界線の引き方のコツ
まず床をざっと眺めまわしてある程度プレイエリアを確定してから、「独自の境界線」で「次へ」を選択すると、エリアを拡げたり削ったりできます。これがおそらく最も速いです。コントローラーなしでも大丈夫です。
遠くに離れるとトラッキングはどうなるか
アプリの実行中に境界線の範囲から出ると、アプリの表示が消え、境界線の中に戻るよう警告ダイアログが表示されます。
パススルーでリセンターした地点から20メートルくらい離れると、離れすぎだと警告ダイアログが表示されます。
パススルーのままエレベーターに乗って上下移動するとブラックアウトします。
境界線を使用しないMRアプリを作るには
全体がパススルーを使用するMR体験で、アプリの実行中を通して境界線を必要としない場合はBoundaryless Appとして構成できます。AndroidManifest.xmlに下記を追加します。
<uses-feature
android:name="com.oculus.feature.BOUNDARYLESS_APP"
android:required="true"/>
没入型VRとMRを切り替えるなど、体験の一部だけ境界線を抑制する場合はContextual BoundarylessのBoundary APIを使用します。OVRManagerのBoundary API SupportをSupportedまたはRequiredにし、Passthrough Supportを有効にしたうえで、パススルーの状態とshouldBoundaryVisibilityBeSuppressedを同期させます。
境界線の抑制はスタンドアロンAPKでのみ動作し、Meta Horizon Link経由ではAndroidManifest.xmlの設定が反映されません。Stage座標をワールド固定用途に使用せず、MRUKのWorld LockingまたはSpatial Anchorsを使用してください。安全上の責任はアプリ開発者にあります。
境界線の表示を切るには
開発時には境界線の表示を切っておくと便利な場合があります。Meta Quest Developer HubのDevice Managerタブで、Boundaryをオフにすると境界線が表示されなくなります。
バッテリーの残量を取得するには
ヘッドセット本体のバッテリー残量はSystemInfo.batteryLevelで取得できます。戻り値は0~1の範囲で、Meta Horizon Linkの場合は-1が返ってきます。
コントローラーのバッテリー残量についてはOVRInput.GetControllerBatteryPercentRemainingというAPIがありますが、Meta XR Core SDK v64現在、0しか返ってこないようです(中を覗くと return 0; とあります)。
Quest本体のTips
apkファイルをインストールするには
Questを開発者モードにした上で、adbコマンドでadb installするか、Meta Quest Developer HubのDevice Managerタブの画面にapkファイルをドラッグ&ドロップするとインストールできます。
Questのストレージにアクセスするには
QuestをPCに接続するとUSBストレージとして認識されます。
もし認識されない場合は、スマートフォンのMeta Questアプリの「開発者モード」をオフ・オンしているとQuestの画面に「データへのアクセスを許可」ダイヤログが出てきて見えるようになる場合があります。
ヘッドセット内の映像を中継表示するには
スマートフォン・タブレット
Meta Questアプリにヘッドセット内の映像をミラーリング表示できます。Questのメニューのシェアボタン>ミラーリングを選択してください。
ブラウザ
ミラーリングページを開いてログインし、Questのメニューのシェアボタン>ミラーリング>コンピューターでヘッドセットの中の映像をミラーリングできます(正方形表示)。フルスクリーン表示も可能です。
PC(USB接続)
PCに Meta Quest Developer Hub をインストール・起動して、Device ManagerタブでCast Deviceのボタンを押すとUSB経由で中継表示できます(正方形表示)。ウィンドウサイズを変更すると大きく表示できます。
scrcpy というツールもありますが、左右2画面の樽型表示になります。
スクリーンショットを撮るには
Oculusボタンを押してダッシュボードを開き、「写真を撮る」ボタンを押すと数秒後に撮影音が鳴ってスクリーンショットが保存されます(正方形)。撮影した画像はQuestをPCに接続して/Oculus/ScreenShotsフォルダから読み出せます。また、Meta Quest Developer HubのFile Managerタブで読み出すこともできます。この方法ではカメラパススルーの表示は記録できません(真っ暗になります)。
右手コントローラーのOculusボタンを押しながらトリガーを引くことでもスクリーンショットが撮影できます(できないこともあるっぽい?)。
Meta Quest Developer HubのDevice ManagerタブのScreenshotのCaptureボタンでスクリーンショットを撮影できます(左右2画面の樽型)。カメラパススルーの表示も記録できます。
Unity の Android Logcat パッケージの Capture Screen のボタンを押すとスクリーンショットが撮影保存できます(左右2画面の樽型)。
動画をキャプチャするには
Quest本体の録画機能
Oculusボタンを押してダッシュボードを開き、「録画」ボタンを押すと動画の録画が開始し、画面の右上にドットが表示されます。もう一度ボタンを押すと録画を終了します。
キャプチャした動画はQuestをPCに接続して/Oculus/VideoShotsフォルダから読み出せます。また、Meta Quest Developer Hub のFile ManagerタブのVideosフォルダで読み出すこともできます。
生成される動画ファイルは片目1画面の正方形で、解像度1024x1024、約24fpsです。
フレームレートの高い動画を撮影したい場合は、adb shell setprop debug.oculus.fullRateCapture 1を実行すると72fpsで録画できます。0を設定すると元に戻ります。
Meta Quest Developer Hub
Meta Quest Developer HubのDevice ManagerタブのRecord Videoボタンで動画を撮影できます。キャプチャを終了すると動画ファイルが C:¥Users¥[ユーザー名]¥AppData¥Roaming¥odh¥captures に保存されます。
生成される動画ファイルは左右2画面の樽型で、解像度3664x1920になります。カメラパススルーの表示も記録できます。Recordボタンの横の設定ボタンでビットレートを設定できます。デフォルトの5Mbpsでは激しい(見るに耐えないレベルの)ブロックノイズが乗るため、高いビットレートに上げたほうがいいです。単眼(Single Eye)で録画する設定もありますが、手元ではエラーで録画が開始できないようです。
adb shell screenrecord
adb shell screenrecordで動画を録画できます。生成される動画ファイルは左右2画面の樽型で、解像度3664x1920、約72fpsです。カメラパススルーの表示も記録できます。
ビットレート40Mbpsで5秒間録画してPCにダウンロードするコマンド例を示します。
$ adb shell screenrecord --time-limit 5 --bit-rate 40000000 /sdcard/video.mp4
$ adb pull /sdcard/video.mp4 [ダウンロード先フォルダ]
Meta Horizon Linkを安定接続するには
PC本体のUSBポートを使用していると、Questがなかなか充電されなかったり、Meta Horizon Linkが安定しなかったりする場合があります。デスクトップPCではUSBカードを使用すると改善される場合があります。
また、WindowsのデバイスマネージャーでUSBハブの「電源の管理>電力の節約のために、コンピューターでこのデバイスの電源をオフにできるようにする」を切るとMeta Horizon Linkが安定するという話があります。
どうしても安定しない場合、Air Linkを試してみるのもおすすめです(Wi-Fi 6Eルーターを使うのがよさそうです)。
QuestとPCをWi-Fi経由で接続するには
Meta Quest Developer HubのDevice ManagerタブでADB over Wi-FiをオンにしてUSBケーブルを抜きます。この状態でアプリをビルド・デプロイしたり、Meta Horizon Link(Air Link)を使ったりすることも可能です。
PCでQuestのブラウザのURLを入力するには
QuestのソフトウェアキーボードでURLを入力するのは大変です。
Meta Quest Developer HubのDevice ManagerタブのDevice Actions > Meta Quest BrowserにURLを入力して簡単にページを開くことができます。
下記adbコマンドでも行けます。
$ adb shell am start -n "com.oculus.vrshell/.MainActivity" -d apk://com.oculus.browser -e uri https://framesynthesis.jp/
Questのアカウントを変更するには
Meta Questアプリとのペアリングを解除するにはファクトリーリセットする必要があります。次の項目を参照してください。
ファクトリーリセットするには
Quest本体のみで工場出荷時の状態に戻すには、電源を一度オフにして、音量マイナスボタンを押しながら電源ボタン長押しで電源を入れます。ロゴが表示されたら電源ボタンだけを離します。メニューが表示されるので、音量ボタンでFactory resetを選択して電源ボタンで実行します。
ファクトリーリセットした後、Meta Questアプリとペアリングして、チュートリアル動画を見てWi-Fiに接続すると、Quest本体とコントローラーのソフトウェアが最新版に更新されます。使用できるようになるまで10分程度は見ておいたほうがよさそうです。
Quest Proでコントローラーの精度が悪くなった
Quest Proはコントローラーにインサイドアウト用のカメラが3つ搭載されていますので、拭いて綺麗にすると直ることがあります。
Questは屋外で使用できるの?
Quest 1の場合、おそらくコントローラーの赤外線LEDが太陽光にかき消されるため、強い晴天下ではコントローラーの6DoFトラッキングができなくなりました。なお、Windows Mixed Realityヘッドセットは同条件で正常に動作しました。
ジェスチャーコントロールを有効にできない
設定 > 動きのトラッキング > ジェスチャーコントロール をオンにしても通常表示されるダイアログが表示されず、ハンドトラッキングに切り替えられない場合があります。
インターネット接続が繋がっていないとこの現象が起きるようです。展示等でハンドトラッキングを使用する場合は、あらかじめジェスチャーコントロールを有効にして持っていきましょう。
Meta Horizon Link編
Meta Horizon Linkで動くアプリをビルドするには
Quest単体向けのときと同様Meta XR Core SDKを使用します。UnityのPlatformを「PC, Mac & Linux Standalone」にして、Project Settings > XR Plug-in ManagementのStandaloneタブでOpenXRとInitialize XR on Startupを有効にします。Meta Horizon LinkをアクティブなOpenXRランタイムにしてビルドすると、Meta Horizon Linkで動く.exeファイルが作成されます。
あらかじめMeta Horizon Linkソフトウェアの設定を変更する必要があります。Meta Horizon Linkソフトウェアを起動して左の設定(Settings)を選択、一般(General)タブを選択して提供元不明(Unknown Sources)をオンにします。この設定は一度変更するとMetaアカウントに保存されます。
PCの画面に別視点の映像を表示するには
展示等でヘッドセットをかぶっていない人にPCディスプレイで観客視点の映像を見せたり、アバターでプレイしている様子を表示したりしたいことがあると思います。
Cameraをシーンに追加し、余分なAudio Listenerを削除した上で以下の設定を行います。レンダーパイプラインによって設定方法が変わります。
ビルトインレンダーパイプライン
PC画面を描画するCameraのTarget EyeをNone (Main Display)に設定して、Depthの数値をヘッドセット側のカメラより大きくします。さらに、下記でヘッドセット側のカメラのミラー表示を無効にできます。
using UnityEngine.XR;
...
XRSettings.gameViewRenderMode = GameViewRenderMode.None;
URP
PC画面を描画するCameraのTarget EyeをNoneに設定して、Priorityの数値をヘッドセット側のCameraより大きくします。
HDRP
CameraのXR Renderingをオフにします。
アプリ起動後にVRモードを有効にしたい
「Unity VR開発メモ(XR Interaction Toolkit + OpenXR Plugin)」の「アプリ起動後にVRモードを有効にしたい」と同様の方法で後からVRモードにできます。
ただし、OpenXR Pluginを使用する場合と異なり、Meta Horizon Linkソフトウェアが起動していない状態でVRモードを有効にしようとしても有効にならない(Meta Horizon Linkソフトウェアが起動しない)ようです。Meta Horizon Linkソフトウェアをあらかじめ起動しておく必要があります。
Meta Horizon LinkでVRモードにならなくなった
Meta Horizon Linkの設定でOpenXRランタイムをアクティブにしているにもかかわらず、OpenXRプラグインのMeta XR feature groupを有効にするとUnityエディタでの再生時にVRモードに移行しない(Meta Horizon Linkの待機画面のままになる)ことがあります。
Steam VRやVIVE Businessストリーミングとの競合によりこの症状が発生することがあるようです。レジストリエディター(regedit)を起動して、一度 HKEY_LOCAL_MACHINE\SOFTWARE\Khronos を削除してみてください。
過去のUnity・Meta XR SDKでのトラブル
以下は主にUnity 2022、Oculus Integration、Oculus XR Pluginを使用していた当時のトラブルです。Unity 6、Unity OpenXR Plugin、現行Meta XR SDKでは修正済みまたは手順が異なるものがあります。新規プロジェクトでは、まずUnityとパッケージを推奨バージョンへ更新し、Project Setup Toolの指摘を修正してください。
Unity 6・Unity 2022.3.39以降でビルドしたapkがダッシュボードにアップロードできない
一部のUnity 2021.3、2022.3、Unity 6で、ビルドしたapkファイルにREAD_PHONE_STATE権限が勝手に追加される不具合がありました。この問題はUnity 2021.3.45f1、2022.3.48f1、6000.0.1f1で修正済みです。まず修正版以降へ更新してください。
ERROR:
The upload could not be completed because your application contains the following Android permissions that are not supported:
- android.permission.READ_PHONE_STATE
Please remove the following permissions and upload your application binary again.
修正版へ更新できない場合の旧版向け回避策として、AndroidManifest.xmlのmanifestタグに
xmlns:tools="http://schemas.android.com/tools"
を追加し、
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
を追加することで権限を削除できました。
OVRExternalCompositionでエラーが出る
Oculus Integrationをプロジェクトをビルドしようとして以下のようなエラーで失敗する場合、
Type '[Oculus.VR]OVRExternalComposition' has an extra field ...
Project Settings > PlayerのScripting Define SymbolsにOVR_ANDROID_MRCを追加するとビルドが通ることがあります。
Unity 2022.3でビルドできない(過去の情報)
(2023年7月)以下のようなエラーでビルドが失敗することがあります。
A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
当時はTarget API Level 32とcompileSdkVersion 33の組み合わせが必要になることがありましたが、この要件は現在では無効です。現行環境ではMinimum API Levelを29以上、Target API LevelをAutomatic (highest installed)にし、Project Setup Toolの診断に従ってください。
以下は旧環境で用いられていた回避策です。現行プロジェクトへ適用しないでください。
// compileSdkVersion **APIVERSION**
compileSdkVersion 33
この設定をした場合、C:\Program Files\Unity\Hub\Editor{Unity Version}\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms フォルダにandroid-33のSDKが存在しないとビルドできませんので注意してください。一度Target API Levelを33に設定してビルドするとダイアログが表示されてSDKがインストールできます。
Unity 2022.3でビルドするとクラッシュする
(2023年8月)Unity 2022.3でビルド後のアプリがQuestでクラッシュする場合があります。Android Logcatのログに
Cause: null pointer dereference
と出力されている場合、グラフィックスAPIをVulkanにすると改善されることがあります(必ずしもこれで安定するとは断言できず、上記エラーメッセージで検索すると結構深刻そうです)。
Oculusプラグインが勝手にオフになる
(2023年3月)Oculusプラグインをオンにできない(プロジェクトを開き直すと勝手にオフになる)現象が起きています。関連するパッケージが一斉にアップデートされているためか、なんらかの相性問題が発生しているようです。
原因の特定はできていないのですが、手元では、以下の要領で一通りアップデートをかけてプラグインの再設定をすると修復されました。
- Unity 2022.2.9(以上)に上げる
- XR Plugin Managemtentを4.3.3(以上)に上げる
- Oculus XR Pluginを3.2.3(以上)に上げる
- Assets/XRフォルダをいったん削除
- Project Settings > XR Plug-in Managementを開いて設定しなおす
Unity 2022.2でビルドするとクラッシュする
下記の要領でXR Plugin Managementパッケージを4.3.1以降に更新すると上手くいくことがあります。ついでにAssets/XRフォルダを一度削除して、Project Settings > XR Plug-in Managementを開いて設定しなおしたほうがいいかもしれません。
Unity 2022.2と旧Oculus XR Pluginでビルドが失敗する
これは旧Oculus XR Plugin向けの記録です。もし下記のようなエラーでビルドが失敗する場合、当時のOculus > Tools > Create store-compatible AndroidManifest.xmlメニューで生成したAndroidManifest.xmlがAndroid 12に対応していないのが原因です。現行プロジェクトではUnity OpenXR PluginとProject Setup Toolを使用し、古いカスタムAndroidManifest.xmlを引き継がないようにしてください。
A failure occurred while executing
com.android.build.gradle.tasks.ProcessLibraryManifest$ProcessLibWorkAction
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
...
android:exported needs to be explicitly specified for element <activity#com.unity3d.player.UnityPlayerActivity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
対処するには、Assets/Plugins/Android/AndroidManifest.xmlのactivityタグのandroid:nameのところに下の要領でandroid:exportedを追加します。
android:name="com.unity3d.player.UnityPlayerActivity" android:exported="true" ...
ダッシュボードへのアップロードが失敗する
Unity 2022.2でビルドしたapkファイルをovr-platform-util.exeでアップロードしようとすると以下のエラーが出ます。
ERROR: 認証中にAPKに問題が見つかりました。APKが「Application Manifest Requirements」の条件を満たしていることをご確認のうえ、もう一度送信してください。
* APKのインストール場所は「自動」(android: AndroidManifest.xml内のinstallLocation)でなくてはなりません。ドキュメントはこちらでご覧ください: https://developers.meta.com/horizon/resources/publish-mobile-manifest/
対処方法として、C:\Program Files\Unity\Hub\Editor\2022.2.9f1\Editor\Data\PlaybackEngines\AndroidPlayer\Apk\LauncherManifest.xml の android:installLocation=“preferExternal” を android:installLocation=“auto” に変更して管理者権限で保存し、ビルドし直すとアップロードできるようになります。下記スレッドで話題になっています。
ビルドのトラブル
ビルドは通るがQuestにインストールできない
Build and Runで下記のようなエラーが出てインストールできないときは、Questでアプリを一度削除してBuild and Runし直しすと上手くいくことが多いです(Android SDKを確認するようにというメッセージで紛らわしいのですが……)。
CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.
ビルド後にQuestで起動しない
Unityのコンソールに
DeploymentOperationFailedException: No activity in the manifest with action MAIN and category LAUNCHER. Try launching the application manually on the device.
というエラーが出ている場合は、Assets/Plugins/Android/AndroidManifest.xmlにMAIN/LAUNCHERを持つActivityがあるか確認してください。旧Oculus XR Pluginが生成した不要なマニフェストなら、バックアップを取ってから削除または再生成し、現行のUnity OpenXR PluginとProject Setup Toolの設定に合わせます。旧パッケージにあったOculus > Tools > Remove AndroidManifest.xmlメニューを前提にしないでください。
困ったとき
Meta Questで目の前に窓が張りつくような表示乱れが発生する
Meta Quest実機で、長方形の窓のような、全然違う場所が表示される領域が目の前にくっついて表示される症状が起きることがあります。原因はSubsampled Layoutのようです。2026年8月現在解決策は見つかっていないため、オフにしてみてください。
アプリから外部ストレージにアクセスできない
Android 11以降ではScoped Storageが適用され、android:requestLegacyExternalStorage=“true"はTarget API Level 30以上で無視されます。現行のQuestアプリでは、この設定を回避策として使用できません。
アプリ固有ファイルはApplication.persistentDataPath等のアプリ専用領域へ保存します。ユーザーが選択した共有ファイルへアクセスする場合はStorage Access Framework、写真や動画等の共有メディアを扱う場合はMediaStoreを使用してください。
その他の Tips
不具合を報告するには
フィードバックセンターにバグトラッカーがありますので、こちらから報告するのがよさそうです。
過去のバージョンのOculus Integrationを参照するには
Oculus Integration SDKのページのVersion表示をプルダウンして選択すると過去のバージョンがダウンロードできます。
Quest 1のアプリを開発するには
Oculus Integration 51.0以降でQuest 1のサポートが打ち切られているため、Quest 1向けに開発する場合は、Oculus Integration 50.0以前を使用する必要があります。過去のバージョンのOculus Integrationは、Oculus Integration SDKのVersion表示をプルダウンして選択するとダウンロードできます。
また、Unity自体のQuest 1サポートはUnity 2021 LTSまでで、Oculus XR Plugin 3.xを使用するようにとのことです。
PlayerPrefsはどこに保存されているの?
通常のAndroidだと/data/data/[パッケージ名]/shared_prefs/[パッケージ名].xmlにあるはずなんですが、Questではアクセスできず、また、アクセスできる場所にそれらしいファイルは見つかりませんでした……。アプリをアンインストールすると初期化できます。
こちらのスレッドで話題になっています。