💡

Meta Questでパススルー時に境界(Guardian)をオフにする方法【Unity】

に公開

前提

  • Unity 6000以降
  • MetaXRSDK v78を使用
  • Meta XR Core SDKをインストール済み
  • OpenXR を有効化済み
  • PackageManagerからUnity OpenXR Metaをインストール済み
  • シーンに OVRPassthroughLayer を1つ配置(パススルー描画用)
  • MetaQuestビルドターゲットで Quest 実機 へデプロイ(Link/Editorでは抑制できません)

手順

AndroidManifest.xml に Boundaryless を宣言する

Asset/Pligins/Android/AndroidManifest.xmlに以下を追加。

<!-- 常時境界をオフにする場合 -->
<uses-feature
    android:name="com.oculus.feature.BOUNDARYLESS_APP"
    android:required="true" />

<!-- 状況に応じて境界をオフにする場合 -->
<uses-feature
    android:name="com.oculus.feature.CONTEXTUAL_BOUNDARYLESS_APP"
    android:required="true" />

<!-- パススルーを使うなら推奨 -->
<uses-feature
    android:name="com.oculus.feature.PASSTHROUGH"
    android:required="true" />

これを入れておくことで、アプリが「境界抑制可能」と認識されます。

XR Plug-in Managementの設定を有効化する

赤枠三点を有効化にする。

image.png

シーンに境界無効化を呼び出すコンポーネントを配置する

以下のクラスを作成し、シーン内に配置する。

using System.Collections;
using UnityEngine;

/// <summary>
/// 起動時に Passthrough を有効化し、Guardian/Boundary の可視化を抑制します。
/// OVR Plugin 使用前提(OVRManager / OVRPassthroughLayer)
/// </summary>
[DefaultExecutionOrder(-1000)]
public class OVRBoundarySuppressor : MonoBehaviour
{
    [Header("Behavior")]
    [Tooltip("シーン開始時に自動で抑制します")]
    public bool suppressOnStart = true;

    [Tooltip("抑制リクエストを出す前に数フレーム待機(初期化待ち)")]
    public int warmupFrames = 1;

    [Header("Optional References")]
    [Tooltip("シーン内の OVRPassthroughLayer。未指定なら自動検索します")]
    public OVRPassthroughLayer passthroughLayer;

    private bool _isSuppressed;

    private void Reset()
    {
        // 自動で見つけておく
        passthroughLayer = Object.FindFirstObjectByType<OVRPassthroughLayer>();
    }

    private void Awake()
    {
        if (passthroughLayer == null)
            passthroughLayer = Object.FindFirstObjectByType<OVRPassthroughLayer>();
    }

    private void Start()
    {
        if (suppressOnStart)
            StartCoroutine(CoSuppressAfterWarmup());
    }

    private IEnumerator CoSuppressAfterWarmup()
    {
        // OVR 初期化待ち(必要に応じてフレーム数を調整)
        for (int i = 0; i < Mathf.Max(0, warmupFrames); i++)
            yield return null;

        EnsurePassthroughEnabled(true);
        SetBoundarySuppression(true);
    }

    /// <summary>
    /// Passthrough の有効/無効を切り替え
    /// </summary>
    public void EnsurePassthroughEnabled(bool enabled)
    {
        if (passthroughLayer == null)
            passthroughLayer = Object.FindFirstObjectByType<OVRPassthroughLayer>();

        if (passthroughLayer != null)
            passthroughLayer.enabled = enabled;
        else
            Debug.LogWarning("[OVRBoundarySuppressor] OVRPassthroughLayer が見つかりません。シーンに追加してください。");
    }

    /// <summary>
    /// 境界可視化の抑制/解除
    /// </summary>
    public void SetBoundarySuppression(bool enable)
    {
#if !UNITY_ANDROID
        Debug.LogWarning("[OVRBoundarySuppressor] 現在のプラットフォームでは Boundary 抑制が動作しない場合があります(Quest 実機でご確認ください)。");
#endif
        // OVRManager.instance が null のケースがあるため、ステートックプロパティ経由に統一
        if (OVRManager.instance != null)
        {
            OVRManager.instance.shouldBoundaryVisibilityBeSuppressed = enable;
        }
        else
        {
            Debug.LogWarning("[OVRBoundarySuppressor] OVRManager.instance が見つかりません。シーンに OVRManager を追加してください。");
        }
        _isSuppressed = enable;

        Debug.Log($"[OVRBoundarySuppressor] Boundary suppression request: {enable}");
    }

    /// <summary>
    /// トグル用(UIボタンやデバッグキーから呼べます)
    /// </summary>
    public void ToggleSuppression()
    {
        SetBoundarySuppression(!_isSuppressed);
    }
}

まとめ

  • Manifest に BOUNDARYLESS_APP / CONTEXTUAL_BOUNDARYLESS_APP / PASSTHROUGH を宣言
  • OpenXR の Boundary Visibility / Camera (Passthrough) / Session を有効化
  • OVRBoundarySuppressor をシーンに置いて起動時に抑制をリクエスト

これで パススルー時に境界(Guardian)を非表示 にできます。

Discussion