» VR開発メモトップへ

Unity VR開発メモ(XR Interaction Toolkit)

最終更新日:2024年01月02日

XR Interaction Toolkitを使用したUnity最新方式でのVRアプリケーション開発方法についてまとめています。

更新履歴

(2024年1月2日)XR Interaction Toolkit 2.5.2でセットアップ手順を再確認、「Viveトラッカーを使用するには」の手順を修正、Windows Mixed Realityの廃止決定を反映
(2023年11月13日)WebXR ExportでXR Interaction Toolkitが動作するようになったのを反映
(2023年6月03日)XR Interaction Toolkit 2.4.0のプレハブ名変更を反映、2.2.0より前のセットアップ方法を削除
(2023年5月23日)「カメラパススルーを使うには」を追加
(2023年5月22日)「ハンドトラッキングを使用するには」にHands Interaction Demoについて追記、「XR Interaction Toolkit Examplesについて」を更新


UnityでVRアプリを作るには

UnityのVR対応の概要

UnityでVR開発する場合、以前はOculus IntegrationSteamVR Plugin等各ベンダー提供のSDKを使用するしかありませんでしたが、現在、Unity純正のXRツールキットであるXR Interaction Toolkitを使用することで、ひとつのプロジェクトでMeta Quest、Valve Index、HTC Vive、PICO 4、Apple Vision Pro等多数のヘッドセットに対応できるようになっています。

OpenXR Pluginや新Input Systemを含め、本ページではこれらUnityの最新機能群を使ってVRアプリケーションを作成する方法について説明します。

XR Interaction Toolkitを使うべきか

XR Interaction Toolkitについて、2024年1月時点では、Meta Quest固有の機能が十分に活用できない、パフォーマンス懸念があるといったデメリットがあります。詳細は「プラットフォームごとの制限事項」を参照してください。

一方で、XR Interaction Toolkitには、さまざまなヘッドセットに対応できるのと、Unityの新しい標準ツールキットを使用するため将来的にも保守しやすい(可能性がある)メリットがあります。

大まかな方針として、Questの機能や性能をフルに引き出す必要がある場合はMetaのSDKを使用し、Quest以外でも動かす必要がある場合はXR Interaction Toolkitを使うといいでしょう。

Questのアプリを開発する場合、Metaプラットフォームの機能やInteraction SDK、Avatars SDKを使用するかどうかも判断ポイントになると思います。

Steam VRヘッドセット用のアプリを開発する場合、SteamVR Pluginはすでに開発が止まっているようですので、基本的にはXR Interaction Toolkitでいいのではと思います。Viveトラッカーもとりあえず使用できるようになりました

OpenXR規格について

OpenXRは、異なるヘッドセットでXRアプリケーションのライフサイクル、ディスプレイの描画、コントローラーの入力等を共通して扱えるように作られたKhronosの標準規格です。主要ベンダーであるMetaValveMicrosoftがOpenXRに全面移行済みで、ヘッドセットの機能がOpenXRの標準APIおよび拡張を通して提供されます。

UnityではOpenXR Pluginを使用してOpenXRヘッドセットの標準的な機能を利用できます。他のゲームエンジンではUnreal EngineやGodotもOpenXRに対応しています。

WindowsのOpenXRランタイムについて

WindowsではMeta、Valve、Varjo他からそれぞれVRのランタイムが提供されており、それぞれOpenXRのAPIに対応しています。現在アクティブなOpenXRランタイムはシステムに保存され、OpenXRアプリを実行するとアクティブなランタイムで起動されます。

これにより注意するべきことが一つあり、アプリがどのOpenXRランタイムを使って起動されるか分かりません。ランタイムによってアプリの動作が微妙に異なる場合があり、また、アプリは自分がどのランタイムで動いているか知ることができません。

対策として、一通りのランタイムで動作確認をしておくか、または、shienaさん制作のOpenXRRuntimeSelectorを使用すると任意のOpenXRランタイムでアプリを起動できます。サンプルプロジェクトもあります。

XR Interaction Toolkitのセットアップ

新規プロジェクトでゼロからXR Interaction Toolkitをセットアップする方法を説明します。

Unityでプロジェクトを作成する

Unity 2021以降で新規プロジェクトを作成します。テンプレートは3DでもURPでも大丈夫です。

XR Interaction Toolkitをインストールする

Window > Package Managerを開きます。左上のPackagesをUnity Registryにして、XR Interaction Toolkitを探してインストールします。見つからなければ+ボタンを押してAdd package by nameでcom.unity.xr.interaction.toolkitをインストールします。

新Input Systemのバックエンドを使用するか確認のダイアログが表示されるので、YesをクリックするとUnityが再起動します。

さらにPackage ManagerでXR Interaction Toolkitを再び選択してSamplesのStarter Assetsをインポートします(下の画像を参照)。

シーンにカメラリグを作成する

上記でインポートしたStarter Assetsの中に設定済みのカメラリグが入っています。シーンのMain Cameraを無効にしてAssets/Samples/XR Interaction Toolkitフォルダの中にあるXR Interaction Setupプレハブをシーンに配置してください。一通りの機能がデフォルトで有効になっていますので、必要であればXR Origin以下に追加されているコンポーネントを適宜無効化します。

また、Assets/Samples/XR Interaction Toolkit/(バージョン番号)/Starter Assets内にDemoSceneというサンプルシーンがあり、上記のカメラリグと一通りのインタラクションのサンプルが配置されています。

OpenXR Pluginのセットアップ

XR Interaction Toolkitを使用して作成したシーンをVRで実行できるように必要なプラグインをインストールします。

Quest LinkおよびSteam VRで実行できるようにする

Edit > Project SettingsでXR Plugin Managementを開き(似たような項目が2つある場合がありますので注意してください)、Install XR Plugin Managementをクリックします。さらにOpenXRのチェックをオンにするとOpenXR Pluginがインストールされます。

Project Validationのページが表示されるので、「Fix All」をクリックします(表示されない場合は黄色い警告アイコンをクリックしてください)。最低ひとつのインタラクションプロファイルを追加してくださいという警告が残っているので、「Edit」をクリックして、「Enabled Interaction Profiles」に使用しているヘッドセットのコントローラーに該当するプロファイルを追加します。

XR Interaction Setupのあるシーンを再生して、VRモードで再生できれば成功です。

Meta Questで実行できるようにする

上記設定に加えて、XR Plugin ManagementのタブでプラットフォームをAndroidに切り替えてこちらでもOpenXRをオンにすると、警告の「!」が表示されます。さきほどと同様、「Oculus Touch Controller Profile」を追加します。

さらに下の「Meta Quest Support」をチェックします。これによりQuest用のAndroidManifest.xmlが生成されるようになります。

OpenXR PluginはIL2CPP / ARM64でなければ動作しませんので、Project Settings > PlayerのAndroidタブでScripting BackendをIL2CPPに変更、Target ArchitecturesのARMv7をオフにしてARM64をオンにします。

AndroidビルドするとQuestに転送・実行されます。

XR Interaction Toolkit Examplesについて

Unity公式からGitHubでXR Interaction Toolkit Examplesというサンプルが公開されています。こちらでXR Interaction Toolkitの使い方を一通り確認できます。

2023年2月にXR Interaction Toolkit 2.3.0にあわせてサンプルが一新され、デフォルトでOpenXR Pluginを使用するように変更されています。バーチャルなジョイスティック操作をするXRJoystickやスライダー操作をするXRSlider等、補助的なコンポーネントも多数含まれています。

プラットフォームごとの注記

Meta

Quest固有の機能を使うには

OpenXR Pluginの代わりにOculus XR Pluginを使うと、リフレッシュレートやCPU・GPUレベルの設定Foveated Rendering等Quest固有の機能の一部を使用できます。Oculus IntegrationをインポートしなくてもOculus XR PluginのAPIを使用できます。

Unity.XR.Oculus.Utils.foveatedRenderingLevel = 3;

OpenXRプラグインでは動作しませんので注意してください。

ハンドトラッキングを使うには

XR Handsパッケージを使用します。「ハンドトラッキングを使用するには」を参照してください。

カメラパススルーを使うには

XR Interaction ToolkitにOpenXR PluginとOculus Integrationを使用して、Questのカメラパススルーを使用できます。XR Interaction Toolkitのセットアップをしたのち以下を行います。

  • Asset StoreからOculus Integrationをインポートする(Assets/Oculus/VRフォルダとOculusProjectConfigだけで大丈夫です)
  • XR Interaction Toolkitのカメラリグ(Complete XR Origin Set Upプレハブ等)のXR OriginにOVR Managerを追加し、Passthrough SupportをSupportedに、Enable Passthroughをオンにする
  • さらにXR OriginにOVR Passthrough Layerを追加し、PlacementをUnderlayに変更する
  • カメラリグのMain CameraのClear FlagsをSolid Colorに、Backgroundを黒の透明(RGBAをすべて0)にする
  • XR Plug-in ManagementでOpenXRプラグインを有効にし、OpenXR Feature GroupsのMeta Quest SupportとMetaXR Featureをオンにする

フォーラムの下記スレッドで話題になっており、スクリーンショットつきの手順が紹介されています。

Oculus Store(App Lab)にゲームをリリースできる?

XR Interaction Toolkit + Oculus XR PluginにOculus Integrationを補助的に使う形でおそらく可能なのではと思うのですが、未確認です。

なお、Oculusボタンを押したときにアプリを一時停止しなければならないという審査項目があり、InputFocusAcquired / InputFocusLostイベントを処理することになっているのですが、OnApplicationFocusでも対応できるようです(Oculusのエンジニアの回答)。

Steam VR

Steamにゲームをリリースできる?

2021年8月よりSteamworksのバーチャルリアリティのターゲットSDKの設定にOpenXRが追加されました。

OpenXR Pluginを使用してSteamのアプリ審査に通過した事例が報告されました。また、Zombieland VRがUnityのOpenXR Pluginを使用しているとのことです。

Viveトラッカーを使用するには

Steam VRのランタイムはOpenXR規格のViveトラッカーの暫定拡張に対応しています(XR_HTCX_vive_tracker_interaction)。OpenXR Pluginではプロファイルを追加することで入力を取得できます。

Unityのフォーラムのこちらの書き込みのHTCViveTrackerProfile.csをプロジェクトにコピーし、15行目のPoseControlの参照をこちらの書き込みに従って書き換えます。

Project Settings > XR Plug-in Management > OpenXRのInteraction ProfilesにHTC Vive Tracker Profileを追加します。

エディタを再生してWindow > Analysis > Input Debuggerを開くと、トラッカーの役割ごとのHTCViveTrackerOpenXR一式がデバイスとして追加され、devicepose等のデータが来ているのが確認できます(なお、ヘッドセットをかぶっていないとデータが来ないようです)。

新Input System対応版のTracked Pose Driverを使用して、下の要領でゲームオブジェクトにViveトラッカーの姿勢を反映できます(なお、Unityを再起動しないと上手く反映されないことがありました)。

オーバーレイアプリは作れる?

XR_EXTX_overlayという暫定拡張がありますが、SteamVRで実装されているか、Unityで使えるかは未確認です。

WebXR

WebXRについて、UnityのWebGLビルドをWebXRに対応させるDe-Panther氏のWebXR Exportがありますが、2023年11月のGitHub最新版でXR Interaction Toolkitが使用できるようになりました。

なお、Unity公式によるWebXRサポートは、ロードマップによるとUnder Consideration(検討中)になっています。現在WebGLのモバイル対応を優先している雰囲気で、2021年頃から2023年11月現在までステータスに変更がなく、だいぶ先になりそうです。

PICO 4

PICO 4向けにビルドするには、PICOの開発者サイトからPICO Unity Integration SDKをダウンロードして適当なフォルダに展開し、Package Managerを開いて左上の+からAdd package from disk…を選択して、展開したフォルダのmanifest.jsonを選択するとPICO Integrationパッケージがインストールされます。

Project Settings > XR Plug-in Managementを開いてAndroidタブを選択するとPICOプラグインが選択できるようになっているので有効にしてBuild and RunするとPICO 4実機で実行できます。Project Settings > PlayerでAndroidのMinimum API Levelを29に設定する必要があります。

トラッキング基準位置について

トラッキング基準位置をXR OriginのTracking Origin Modeで設定できます。ヘッドセットによってデフォルトのモードが異なるので、明示的にモードを設定しておいたほうがいいでしょう(QuestではDevice、ViveではFloorなど)。

Floor

Unityのカメラを配置した場所が、トラッキング空間の中央地面になります。通常、カメラを(0, 0, 0)等に配置してその周辺にシーンを構築することになると思います。部屋を歩きまわったりするコンテンツはこのモードに設定します。

ちなみにXR Interaction Toolkit ExamplesのWorldInteractionDemoはなぜか床の高さがY=1になっています。

Device

Unityのカメラを配置した場所が、プレイヤーの頭の位置になります。Camera Y Offsetでカメラの高さをオフセットできます。

コントローラーの入力について

コントローラーの状態はUnityの新Input Systemを使用して取得できます。新Input Systemの基本的な理解が必須になりますので、もし新Input Systemに馴染みがない場合は、Unity for Proに「Unityの新入力システム・Input Systemを使おう」という記事を執筆しましたので、まずこちらを読んでみてください。

XR Interaction Toolkitではさらにちょっとややこしい仕組みが用いられています。

まず、Project SettingsでXR Plug-in Management > OpenXRを開いて、Interaction Profilesにプロファイルを登録すると、OpenXR規格の各コントローラーのプロファイルがInput Systemのコントローラーのレイアウトとしてマッピングされます。通常、Steamで一定のシェアがあるOculus Touch、Valve Index、HTC Viveの3つのController Profileを一通り登録することになると思います。

XR Interaction ToolkitにサンプルとしてついてくるXRI Default Input Actionsに、XR Interaction Toolkitで使用するアクションが一通り登録されています。XRI HMD、XRI LeftHand、XRI RightHandのアクションマップにXR Controller > XR Controller (LeftHand / RightHand) > Optional Controlsのコントロールを使用するアクションが登録されています。

Optional Controlsというのは、ベースとなるレイアウト(例えばXRControllerクラス)には存在せず、派生したレイアウト(例えばOculusTouchControllerクラス)には存在するかもしれないコントロールです(Input SystemのEditorInputControlLayoutCache.csにコメントで説明があります)。

たとえばアクションにOptional Controls > triggerPressedをバインドすると、下記の「コントローラーのマッピング」の表の「Oculus Touch Controller (OpenXR)」「Valve Index Controller (OpenXR)」「HTC Vive Controller (OpenXR)」に登録されているtriggerPressedにアクセスできます。これによって、登録されているプロファイルに依らず、一つのXRI Default Input Actionsから各プロファイルのコントローラーにアクセスできるようになっています。

この仕組みを用いず、ヘッドセットによって使用するコントロールを変更する場合は、プロファイルが登録されているとXR Controllerの下に「Oculus Touch Controller (OpenXR)」「Valve Index Controller (OpenXR)」「HTC Vive Controller (OpenXR)」が出てきますので、これらを使用します。

公式ドキュメントでは下記ページに解説があります。

コントローラーのマッピング

プロファイルによってInput Systemに登録される各コントローラーの入力のマッピングと特徴を示します。実際の動作は、エディタ再生時にWindow > Analysis > Input Debuggerでデバイスの状態を確認してみるのがおすすめです。

Oculus Touch Controller (OpenXR)

Path Action / Control Type 種類
trigger Value (Axis) トリガー(人差し指)
triggerPressed / triggerTouched Button トリガー(人差し指)
grip Value (Axis) グリップ(中指)
gripPressed Button グリップ(中指)
thumbstick Value (Vector 2) スティック(親指)
thumbstickClicked / thumbstickTouched Button スティック(親指)
primaryButton / primaryTouched Button A、X
secondaryButton / secondaryTouched Button B、Y
menu Button メニューボタン

Touchコントローラーは最も標準的な入力を持ちます。なお、Oculus Integrationで取得できる近接センサー(NearTouch)の入力がOpenXRでは取れないようです。

Valve Index Controller (OpenXR)

Path Action / Control Type 種類
trigger Value (Axis) トリガー(人差し指)
triggerPressed / triggerTouched Button トリガー(人差し指)
grip Value (Axis) グリップ(手のひら)
gripPressed Button グリップ(手のひら)
gripForce Value (Axis) グリップ(手のひら)
thumbstick Value (Vector 2) スティック(親指)
thumbstickClicked / thumbstickTouched Button スティック(親指)
trackpad Value (Vector 2) トラックパッド(親指)
trackpadForce Value (Axis) トラックパッド(親指)
trackpadTouched Button トラックパッド(親指)
primaryButton / primaryTouched Button A
secondaryButton / secondaryTouched Button B
system / systemTouched Button システムボタン

KnucklesはTouchコントローラーに比べて入力が多いです。

triggerの値について、0の状態からトリガーを引くにしたがって1まで徐々に上がっていきます。最後にカチッとクリックするとtriggerPressedがオンになります。

グリップの入力値にやや癖があります。手を広げた状態から握った形にするにしたがってgripが0~1で上がっていき、握った形にすると(触れただけで)gripPressedがオンになります。握った状態からさらに力を加えて握り込むとgripForceが0~1で上がります。

システムボタンはタッチしか取れない(systemがオンにならない)ようです。

HTC Vive Controller (OpenXR)

Path Action / Control Type 種類
trigger Value (Axis) トリガー(人差し指)
triggerPressed Button トリガー(人差し指)
gripPressed Button グリップ(中指)
trackpad Value (Vector 2) トラックパッド(親指)
trackpadClicked / trackpadTouched Button トラックパッド(親指)
menu Button メニューボタン

ViveコントローラーはTouchコントローラーやKnucklesに比べて入力が少ないため、他のヘッドセット向けに作ったものを移植しようとすると「入力が足りない!」となりがちなので、注意が必要です。

triggerの値について、0の状態からトリガーを引くにしたがって0.75~0.8くらいまで徐々に上がっていき、最後にカチッとクリックすると1にジャンプします。また、このときにtriggerPressedもオンになります。トリガーのタッチ判定(triggerTouched)は取得できません。

丸形のトラックパッドの名前は「trackpad」ですので注意してください(touchpadと間違いやすいです)。

コントローラーを振動させるには

LeftHand Controller・RightHand Controllerに追加されているXR Controller (Action-based)コンポーネントにSendHapticImpulseメソッドがあります。強さと長さ(秒)を指定できます。

また、OpenXR Plugin 1.3.1ではOpenXRInputに振動関係のメソッドが追加されています。Input SystemでアクションをAction Type = Pass Through、Control Type = HapticにするとXRControllerにhapticが見つかりますので、下記を実行します(が、上手く動かない気がする)。

OpenXRInput.SendHapticImpulse(inputAction, amplitude, durationSec, inputAction.activeControl?.device);

コントローラーの向きについて

OpenXR規格のコントローラーの姿勢には、手のひらの重心位置のgripとコントローラー先端のaimの2つがあります。Input SystemのdevicePoseがgripに、pointerPoseがaimに対応しています。

The OpenXR Specificationの"Figure 2. Example grip and aim poses for generic motion controllers"より引用)

XR Interaction Toolkitに付属しているXRI Default Input Actionsでは、コントローラーの姿勢をまずaimに相当するpointerPosition/Rotationから取得してくるようになっていますので、gripの姿勢が必要な場合はこれを削除してdevicePosition/Rotationに変更します。

なお、本来はdevicePose/pointerPoseを使ったほうがよく、devicePosition/RotationとpointerPosition/Rotationは互換性のために残されているものとのことです。

コントローラーの種類を識別するには

接続されているコントローラーによって動作を変えたい場合があります(例えばコントローラーによって向きが微妙に違ったりします)。少々トリッキーになりますが、下記の要領でInput Systemを使用してコントローラーの種類を識別できます。

using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;

public class ControllerIdentifier : MonoBehaviour
{
    void Start()
    {
        // ビルドした実行ファイルで、起動時にVRコントローラーがアクティブになっている場合は
        // ここで検出される(onDeviceChangeは呼ばれない)。
        foreach (var device in InputSystem.devices)
        {
            IdentifyDevice(device);
        }
    }

    void OnEnable()
    {
        InputSystem.onDeviceChange += OnDeviceChange;
    }

    void OnDisable()
    {
        InputSystem.onDeviceChange -= OnDeviceChange;
    }

    void OnDeviceChange(InputDevice inputDevice, InputDeviceChange inputDeviceChange)
    {
        if (inputDeviceChange == InputDeviceChange.Added)
        {
            // エディタで再生した場合、またはアプリを起動してから
            // VRコントローラーをアクティブにした場合はここで検出される。
            IdentifyDevice(inputDevice);
        }
    }

    void IdentifyDevice(InputDevice inputDevice)
    {
        // VRコントローラーかどうかをチェックする。
        if (!inputDevice.usages.Contains(CommonUsages.LeftHand) &&
            !inputDevice.usages.Contains(CommonUsages.RightHand)) return;
        
        if (inputDevice.displayName.Contains("HTC Vive"))
        {
            ...
        }
        if (inputDevice.displayName.Contains("Touch"))
        {
            ...
        }
        if (inputDevice.displayName.Contains("Index"))
        {
            ...
        }
    }
}

displayNameは以下のようになります。

コントローラーの種類 displayName
Oculus Touchコントローラー Oculus Touch Controller OpenXR
Knuckles Index Controller OpenXR
Viveコントローラー HTC Vive Controller OpenXR

なお、ヘッドセットについてはOculus RiftでもHTC Viveでも"Head Tracking - OpenXR"が返ってくるため識別できません。

デバイスの識別については下記スレッドで話題になっています。

ハンドトラッキングを使用するには

(2023年1月)Unity公式のXR Handsパッケージでハンドトラッキングが使用できるようになりました。Meta QuestおよびQuest Linkでの動作を確認しています。

XR Handsパッケージはハンドトラッキングのためのベースクラスとユーティリティのみを含んでいて、ハンドトラッキングに対応している各プラットフォームのプラグインが必要とのことです(現状はOpenXR Pluginのみです)。また、XR Interaction Toolkitに各種インタラクションのサンプルが追加されています。

ハンドトラッキングを使用するには、XR Interaction Toolkitの基本設定を済ませた上で、XR Handsパッケージ(com.unity.xr.hands)をインストールして、さらにSamplesのHandVisualizerをインポートします。

OpenXR Plugin 1.6.0以上が必要なので、下記要領でアップデートします。

さらにOpenXRプラグインのハンドトラッキング関連のサブシステムを有効にします。

Assets/Samples/XR Hands/(バージョン名)/HandVisualizer/HandVisualizer.unityシーンをビルドするとMeta Questで手が表示されるはずです。また、ハンドトラッキングを使用できる状態にしてQuest Linkを使用すると、エディタ再生でも動作します。

さらに、XR Interaction ToolkitのパッケージのSamplesからHands Interaction Demoをインポートすると、物をつかんだり、ボタンを押したり、UGUIを操作したりできるサンプルシーンが入っています。使用するコンポーネントはモーションコントローラー操作の場合とほぼ同じです。

XR Plugin ManagementのTips

Oculusのプラグインを有効にできなくなった

OpenXRプラグインのチェックを入れるとOculusプラグインを有効にできなくなります。

Assets/XR/Loadersフォルダをいったん削除して、Project Settings > XR Plugin Managementを開き直すと復活します。

Initialize XR on Startupをスクリプトで切り替えたい

ひとつのプロジェクトからVRのバージョンと非VRのバージョンをビルドしたい場合があります(例えばQuestと通常のAndroidスマートフォン)。下記の要領でInitialize XR on Startupをスクリプトから切り替えられます。

public static void SetInitializeXROnStartup(BuildTargetGroup buildTargetGroup, bool enabled)
{
    var xrGeneralSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(buildTargetGroup);
    xrGeneralSettings.InitManagerOnStart = enabled;
    EditorUtility.SetDirty(xrGeneralSettings);
    AssetDatabase.SaveAssets();
}

なお、Oculusのプラグインを有効にしたままビルドしてAndroidスマートフォンで実行するとエラーが出ます。次の項目の方法でプラグインを無効にする必要があります。

プラグインをスクリプトで切り替えたい

CI等でビルドするときに、プラットフォームにあわせて使用するプラグインを切り替えたい場合があります。こちらのGistをご利用ください。

下記の要領で使用できます。

using UnityEditor;
using FrameSynthesis.XR;

public static class PluginSwitcher
{
    [MenuItem("Debug/Enable OpenXR Plugin")]
    public static void EnableOpenXRPlugin()
    {
        XRPluginManagementSettings.EnablePlugin(BuildTargetGroup.Android, XRPluginManagementSettings.Plugin.OpenXR);
        XRPluginManagementSettings.DisablePlugin(BuildTargetGroup.Android, XRPluginManagementSettings.Plugin.Oculus);
    }

    [MenuItem("Debug/Enable Oculus Plugin")]
    public static void EnableOculusPlugin()
    {
        XRPluginManagementSettings.EnablePlugin(BuildTargetGroup.Android, XRPluginManagementSettings.Plugin.Oculus);
        XRPluginManagementSettings.DisablePlugin(BuildTargetGroup.Android, XRPluginManagementSettings.Plugin.OpenXR);
    }
}

なお実行時にプラグインを切り替えることはできません。

アプリ起動後にVRモードを有効にしたい

アプリを非VRモードで起動して、あとからVRモードに切り替えたい場合があります。Project SettingsのXR Plugin ManagementでInitialize XR on Startupをオフにして、XR Plugin ManagementのこちらのページにあるManualXRControlクラスを使用して、以下の要領でVRモードに切り替えられます。

var manualXRControl = new ManualXRControl();
StartCoroutine(manualXRControl.StartXRCoroutine());

同様にStopXRを呼ぶとVRモードを終了にします(なぜかprivateメソッドになっているのでpublicにしてください)。

OpenXRのランタイムとしてSteamVRを使用している場合、SteamVRを起動せずにアプリを起動して、VRモードに切り替えるとSteamVRが起動するといった挙動が可能です

現在VRモードかどうかを調べるには

以下で調べられます。

// activeLoaderがnull以外ならVRモード
XRGeneralSettings.Instance && XRGeneralSettings.Instance.Manager.activeLoader != null

トラッキング基準位置を変更したい(XR Interaction Toolkit非使用時)

XR Plugin Managementでトラッキング基準位置を設定するには以下のようにします。TrackingOriginModeFlagsはDeviceやFloorが使用できます。

var subsystems = new List<XRInputSubsystem>();
SubsystemManager.GetInstances(subsystems);
foreach (var subsystem in subsystems)
{
    subsystem.TrySetTrackingOriginMode(TrackingOriginModeFlags.Device);
}

なお以前のXRDevice.SetTrackingSpaceTypeは非推奨になっており、環境によっては動作しなくなっているようです。

XR Interaction ToolkitのTips

再生してもヘッドトラッキングが動かない

Windows > Analysis > Input Debuggerを開いて左上のOptions > Lock Input to Game Viewがオンになっていることを確認してください。

Input System 1.3.0では設定がProject Settings > Input System Package > Play Mode Input Behaviourに移動しています。

再生してもコントローラーが動かない

再生してもコントローラーが原点のまま赤い線が床に張りついている場合、まずInput Actionを有効にするコンポーネントを追加しているかを確認してください。シーンに空のゲームオブジェクトを作成し、Input Action Managerコンポーネントを追加して、XRI Default Input Actionsアセットを設定します。

また、XR Interaction ToolkitとOculus Integration(40以降?)のOpenXRバックエンドを同じプロジェクトに入れたときにコントローラーが動かないトラブルが発生しています。XR Plug-in Management > OpenXRのOculusXR Featureを無効にすると動作します(が、Oculus固有機能は使えなくなります)。下記スレッドで話題になっています。

連続的に移動できるようにするには

XR OriginにLocomotion Systemを追加してXR Originを割り当て、Continuous Move Providerを追加してアクションを設定します。さらに、Character Controllerが追加されていると座標を直接動かすのではなくCharacter Controllerを使って移動するようになります。さらにSnap Turn ProviderまたはContinuous Turn Providerを追加して回転できるようにします。

XR Interaction Toolkit Examplesでは、XRRigDemoのLocomotion Scheme ManagerのMove SchemeをContinuousにするとContinuous Move Providerが使用されます。

物をつかめるようにするには

ColliderのついたゲームオブジェクトにXR Grab Interactableを追加します。シーンのどこかにXR Interaction Managerが追加されたゲームオブジェクトが必要です。

UGUIのボタンを操作できるようにするには

Canvasをワールド空間に配置して(Render ModeをWorld Spaceにする)、Tracked Device Graphic Raycasterコンポーネントを追加します。また、EventSystemにXR UI Input Moduleを追加します。

XR Interaction Toolkit ExamplesのWorldInteractionDemoシーンにあるUI Intertactionが参考になります。

物をつかんだときに位置・向きが変わらないようにしたい

物の位置を微調整したい場合に、デフォルトの動作は都合が悪いです。リグの左手・右手に下記のようなスクリプトを追加し、XR Ray InteractorコンポーネントのInteractable EventsのSelect Enteredから呼び出してください。

public class KeepTransformOnGrab : MonoBehaviour
{
    public void OnSelectEntered(XRRayInteractor xrRayInteractor)
    {
        xrRayInteractor.attachTransform.position = xrRayInteractor.selectTarget.transform.position;
        xrRayInteractor.attachTransform.rotation = xrRayInteractor.selectTarget.transform.rotation;
    }
}

オブジェクト側で動作させたい場合は、XR Grab Interactableコンポーネントが追加されたオブジェクトに下記スクリプトを追加します。

public class KeepTransformOnGrab : MonoBehaviour
{
    public void OnSelectEntered(XRGrabInteractable xrGrabInteractable)
    {
        xrGrabInteractable.selectingInteractor.attachTransform.position = transform.position;
        xrGrabInteractable.selectingInteractor.attachTransform.rotation = transform.rotation;
    }
}

物をつかむ場所を左手と右手で変更したい

XR Grab Interactableが追加されたオブジェクトに下記のようなスクリプトを追加し、Interactable EventsのSelect Enteredから呼び出します。

public class GrabPointSelector : MonoBehaviour
{
    [SerializeField] Transform leftHand;
    [SerializeField] Transform rightHand;

    public void OnSelectEntered(XRGrabInteractable xrGrabInteractable)
    {
        var isLeftHand = xrGrabInteractable.selectingInteractor.name.Contains("Left");
        xrGrabInteractable.attachTransform = isLeftHand ? leftHand : rightHand;
    }
}

XR Interaction Toolkitの開発ロードマップを知りたい

Unity公式サイトのPlatform RoadmapのAR/VRページにて、XR Interaction Toolkit、AR Foundationおよびプラットフォームサポートのロードマップが公開されています。

PCの画面に別視点の映像を表示するには

Quest LinkやSteamVR向けにビルドする場合、ヘッドセットをかぶっていない人にPCのディスプレイで観客視点の映像を表示したい場合があると思います。

Cameraをシーンに追加し、余分なAudio Listenerを削除した上で以下の設定を行います。レンダーパイプラインによって設定方法が変わります。

ビルトイン・URP

CameraコンポーネントのTarget Eyeを「None (Main Display)」に設定します。PC側のカメラのDepth (Priority)をヘッドセット側のカメラより大きくしておく必要があります。

HDRP

CameraコンポーネントのXR Renderingをオフにします。

ヘッドセットなしでXR Originを操作するには

XR Device Simulatorを使用すると、キーボード・マウスを使ってXR Originのヘッドセットやコントローラーを操作できます。Input Systemに対応したXR Originを使用する必要があります。

使用するには、Package ManagerのXR Interaction ToolkitのSamplesからXR Device Simulatorをインポートして、インポートされたXR Device SimulatorプレハブをHierarchyにドロップします。Project Settings > XR Plug-in ManagementのInitialize XR on Startupをオフにした状態で再生してください。

デフォルトでの操作はXR Device Simulatorオブジェクトで設定されており、以下のようになっています(全部の操作をここで網羅することはしませんので確認してください)。

右クリックを押しながらで頭を、Shiftとスペースを押しながらで左右のコントローラーを選択して、マウスホイールと中ボタンのドラッグで移動・回転させる感じです。

キーボード・マウス操作 XR Origin
右クリック+マウス移動 ヘッドセット移動(上下左右)
右クリック+ホイール ヘッドセット移動(前後)
右クリック+中ドラッグ ヘッドセット回転
Shift+マウス移動 左コントローラー移動(上下左右)
Shift+ホイール 左コントローラー移動(前後)
Shift+中ドラッグ 左コントローラー回転
スペース+マウス移動 右コントローラー移動(上下左右)
スペース+ホイール 右コントローラー移動(前後)
スペース+中ドラッグ 右コントローラー回転
Shift+W/A/S/D 左スティック操作
スペース+W/A/S/D 左スティック操作

なお、再生するとヘッドセットとコントローラーがゼロ位置になってしまいますが、今のところデフォルト位置を設定する方法はないようです。

今のところは、どうしてもヘッドセットが使用できないときの代用手段として使用するのがいいのではと思います。

実装的には、Input SystemにXRSimulatorHMDやXRSimulatedControllerを追加して設定されたInputActionReferenceで操作しているようです。

書いた人:こりん(@korinVR
» VR開発メモトップへ