0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Meta Quest】XR Interaction ToolkitのXR Device Simulatorをオンにした状態でLink接続のデバッグをするとバグる

0
Last updated at Posted at 2025-12-07

アドカレ

KENTOのひとりアドカレ8日目の記事です。
https://qiita.com/advent-calendar/2025/kento

環境情報

ツール/SDK バージョン
Unity 6000.0.62f1
Meta XR Core SDK 81.0.0
Open XR Plugin 1.16.0
XR Interaction Toolkit 3.0.9
XR Hands 1.7.1

事前準備は以下の通りです。

XR Device SimulatorとLinkの競合

XR Device Simulatorをオンにした状態でLinkに接続して動作確認しようとすると、互いのトラッキングシステムが競合し、正常な挙動となりません。

解決策

基本動作はシミュレーターを有効とし、Link接続時のみシミュレーターをオフにする仕様を目指しました。

まず、必要な情報としてはLink接続状態かどうかの情報です。これは、以下のコードで取得できました。

using UnityEngine;
using UnityEngine.XR.OpenXR;

public static class MetaQuestLinkChecker
{
    /// <summary>
    /// Link使用中かどうか。
    /// RuntimeName が Empty → 非 Link
    /// Empty 以外 → Link
    /// </summary>
    public static bool IsLink => !string.IsNullOrEmpty(_runtimeName);
    
    private static string _runtimeName;

#if UNITY_EDITOR  [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    private static void Initialize()
    {
        _runtimeName = OpenXRRuntime.name;

        Debug.Log($"[AutoActivateDeviceSimulator] Initialized: RuntimeName='{_runtimeName}', IsLink={IsLink}");
    }
#endif
}

次に、IsLinkに応じたXR Device Simulatorの無効化です。ただ、これが少し面倒で、以下パスに設定ファイルが配置してあるのですが、肝心のオン/オフ制御用パラメータはinternalで定義されており、外部からの動的な変更を想定したつくりではありませんでした。

Assets/XRI/Settings/Resources/XRDeviceSimulatorSettings.asset

XRIのシミュレーター設定用コード
using Unity.XR.CoreUtils;
using UnityEngine.XR.Interaction.Toolkit.Utilities;

namespace UnityEngine.XR.Interaction.Toolkit.Inputs.Simulation
{
    /// <summary>
    /// Configuration class for XR Device Simulator which
    /// stores settings related to automatic instantiation.
    /// </summary>
    [ScriptableSettingsPath(ProjectPath.k_XRInteractionSettingsFolder)]
    class XRDeviceSimulatorSettings : ScriptableSettings<XRDeviceSimulatorSettings>
    {
        [SerializeField]
        bool m_AutomaticallyInstantiateSimulatorPrefab;

        /// <summary>
        /// Setting this value to <see langword="true"/> will tell the <see cref="XRDeviceSimulatorLoader"/> to look for and automatically
        /// add the <see cref="simulatorPrefab"/> to the current scene if it does not already exist.
        /// </summary>
        internal bool automaticallyInstantiateSimulatorPrefab
        {
            get => m_AutomaticallyInstantiateSimulatorPrefab;
            set => m_AutomaticallyInstantiateSimulatorPrefab = value;
        }

        [SerializeField]
        bool m_AutomaticallyInstantiateInEditorOnly = true;

        /// <summary>
        /// Enable to only automatically instantiate the <see cref="simulatorPrefab"/> if the application is running inside the Unity Editor,
        /// preventing it from automatically appearing in standalone builds. Disable to allow the simulator to be created in standalone builds.
        /// </summary>
        /// <remarks>
        /// Setting this value to <see langword="true"/> will limit the <see cref="XRDeviceSimulatorLoader"/> to
        /// only automatically instantiate the <see cref="simulatorPrefab"/> if the application is running inside the Unity Editor.
        /// This property is only used if <see cref="automaticallyInstantiateSimulatorPrefab"/> is enabled.
        /// </remarks>
        internal bool automaticallyInstantiateInEditorOnly
        {
            get => m_AutomaticallyInstantiateInEditorOnly;
            set => m_AutomaticallyInstantiateInEditorOnly = value;
        }

        [SerializeField]
        GameObject m_SimulatorPrefab;

        /// <summary>
        /// This is the prefab to instantiate when <see cref="automaticallyInstantiateSimulatorPrefab"/> is set to <see langword="true"/>.
        /// </summary>
        internal GameObject simulatorPrefab
        {
            get => m_SimulatorPrefab;
            set => m_SimulatorPrefab = value;
        }

    }
}

よって、パラメータの動的変更は諦めて、シーン上のシミュレーターをシーンロード直後に破棄する方針を採用しました。

#if UNITY_EDITOR
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit.Inputs.Simulation;

public class AutoActivateDeviceSimulator : MonoBehaviour
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    private static void DestroySimulatorOnLink()
    {
        if (MetaQuestLinkChecker.IsLink && XRDeviceSimulator.instance)
        {
            Destroy(XRDeviceSimulator.instance.gameObject);
            Debug.Log("[AutoActivateDeviceSimulator] Link Runtime detected. XR Device Simulator instance destroyed.");
        }
    }
}
#endif

これらのコードにより、非Link接続時にはシミュレーターが利用され、Link接続時には自動的にシミュレーターの無効化を行うという構造を実現できました。

おまけ

Linkの接続状態を取得できるのは他の箇所でも活躍しました。

以前の記事で、コントローラーの位置がずれる問題に触れましたが、シミュレーター上ではその不具合が再現しないため、今どの環境で動いているのか場合分けが必要でした。

【参考リンク】:【Meta Quest】XR Interaction Toolkitを導入する

MetaQuestLinkCheckerを用いれば、以下のように解決可能です。

コントローラーのゲームオブジェクトにアタッチ
using UnityEngine;

public class FixControllerTransform : MonoBehaviour
{
    private void Awake()
    {
        var fixEuler = new Vector3(0,180,180);
        var originalEuler = new Vector3(0,180,0);
        
#if UNITY_EDITOR
        transform.localEulerAngles = MetaQuestLinkChecker.IsLink ? fixEuler : originalEuler;
#else
        transform.localEulerAngles = fixEuler;
#endif
        
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?