Godot で Spatial コンテナを使用する

対象となる XR デバイス
このガイダンスは、次のようなタイプの XR デバイス向けのエクスペリエンスを構築する際に役立ちます。
XR ヘッドセット
有線 XR グラス

空間コンテナを使用すると、アプリはフルスペース モードでシステム管理の 3D ボリューム境界ボックス内に 3D OpenXR コンテンツをレンダリングしたり、実行時に全画面表示の無制限のエクスペリエンスに移行したりできます。

このガイドに沿って、プロジェクトで Spatial Container を構成して使用します。

Android XR のフルスペース モードで動作する複数の空間コンテナ。
図 1. フルスペース モードの空間コンテナ。床に固定された 3D 地形コンテナと、2D UI とペア設定された 3D モデルが含まれます。

空間コンテナの仕組み

プロジェクト設定で [Spatial Container] を有効にすると、次のようになります。

  • アクティブな 3D シーン全体は、シーンの原点 (0, 0, 0) を中心とする 1 つのプライマリ空間コンテナ内に配置されます。個々の Node3D ノードにタグを付けたり、割り当てたりして、コンテナ内に配置する必要はありません。
  • アプリは、プロジェクト設定で構成された境界モード(Bounded または Immersive)と初期境界寸法を使用して、管理対象のフルスペース モードで起動します。境界モードでは、境界ボックスの寸法外に広がるシーン内の 3D ジオメトリが自動的にクリップされます。
  • デフォルトでは、Android XR システムはウィンドウ コントロールを提供します。これにより、ユーザーは 3D 空間で境界付きコンテナをグラブ、移動、再配置したり、最小化して閉じたりできます。実行時に、アプリはコンテナのサイズを変更し、境界モード(OpenXRSpatialContainerState.BOUNDED)と全画面没入モード(OpenXRSpatialContainerState.IMMERSIVE)を切り替えて、OpenXRSpatialContainerExtension シングルトンを使用して境界と状態の変更に対応できます。

前提条件

開始する前に、開発環境と対象デバイスが次の要件を満たしていることを確認してください。

  • Godot のバージョン: Godot 4.8-dev 以降。
  • プロジェクトの設定: Godot Engine プロジェクトの設定ガイドのすべての手順を完了します。
  • Godot OpenXR Vendors Plugin: Godot OpenXR Vendors Plugin のバージョン 5.2 以降をインストールします。これにより、Android XR 固有の拡張機能のサポートが有効になります。
  • 対象デバイス: Spatial API レベル 4 以降をサポートする Android XR デバイス。実行時に OpenXRSpatialContainerExtension.is_enabled() を呼び出して、デバイスで拡張機能が利用可能かどうかを確認します。

プロジェクト設定で空間コンテナを有効にする

OpenXR、空間コンテナ、自動実行時の権限、アルファ ブレンド パススルーを有効にするようにプロジェクト設定を構成します。

  1. [プロジェクト] > [プロジェクト設定] を開きます。
  2. [プロジェクト設定] ウィンドウの右上にある [Advanced Settings] を有効にします。
  3. [General] > [XR] > [Shaders] に移動し、[Enabled] を選択します。
  4. [General] > [XR] > [OpenXR] に移動し、次の設定を構成します。
    • [Enabled] を選択して、プロジェクトで OpenXR を有効にします。
    • [Environment Blend Mode] を [Alpha Blend] に設定します。
  5. [OpenXR] の [Extensions] セクションに移動し、次の設定を行います。
    • [Automatically Request Runtime Permissions] を選択すると、Android マニフェストで宣言されている XR 実行時の権限について、アプリの起動時にユーザーに自動的にプロンプトが表示されます。
    • [Spatial Container] サブセクションで、[Enabled] を選択します。
    • [Bounds Mode] を [Bounded] に設定すると 3D 境界ボックスで起動し、[Immersive] に設定すると全画面没入モードで起動します。
    • [Bounds] を、初期の幅、高さ、奥行きの寸法(メートル単位、Vector3(1.0, 1.0, 1.0) など)に設定します。
  6. [General] > [Rendering] > [Viewport] に移動し、[Transparent Background] を選択します。

Android のエクスポート、権限、フルスペース モードを構成する

次に、Android のエクスポート プリセット、権限、アクティビティ開始モードを構成して、空間コンテナを有効にしたフルスペース モードでアプリが実行されるようにします。

Android のエクスポート プリセットを構成する

  1. [Project] > [Export...] に移動し、Android エクスポート プリセットを選択します。
  2. [Gradle Build] で [Use Gradle Build] を選択し、[Min SDK] を 34 以降に設定します。

    有効にする

  3. [XR Features] で、[XR Mode] を [OpenXR] に設定し、[Enable AndroidXR Plugin] を選択します。

    [

  4. [Android XR Features] で [Use Experimental Features] を選択します。

フロアロック用のシーン認識権限を追加する

基本的な空間コンテナの作成とレンダリングには、危険な実行時の権限は必要ありません([Use Experimental Features] が有効になっている場合、android.permission.HEAD_TRACKING はマニフェストに自動的に追加されます)。ただし、空間コンテナを物理的な床にロックして固定するなど、シーン認識機能を使用するアプリでは、実行時に android.permission.SCENE_UNDERSTANDING_COARSE 権限を宣言してリクエストする必要があります。

Android XR の権限の詳細については、XR の権限についてをご覧ください。アプリでフロアロックまたはシーン認識を使用する場合は、android.permission.SCENE_UNDERSTANDING_COARSE を宣言してリクエストします。

  1. [Project] > [Export...] > Android] に移動し、[Permissions] > [Custom Permissions] に移動して android.permission.SCENE_UNDERSTANDING_COARSE を追加します。

  2. [Project Settings] > [General] > [XR] > [OpenXR] > [Extensions] で [Automatically Request Runtime Permissions] を選択すると、OpenXR の起動時にアプリが自動的に権限をリクエストします。代わりに GDScript で権限を手動でリクエストする必要がある場合は、OS.request_permission() を呼び出します。

    if not OS.get_granted_permissions().has("android.permission.SCENE_UNDERSTANDING_COARSE"):
        OS.request_permission("android.permission.SCENE_UNDERSTANDING_COARSE")
    

フルスペース モードを構成する

Android XR の空間コンテナは、フルスペース モード(XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED)のみをサポートしています。Android アクティビティが、カスタムビルド テンプレート(android/build/AndroidManifest.xml、[Project] > [Install Android Build Template...] を使用してインストール)で XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED を宣言していることを確認します。

<manifest ...>
    <application ...>
        <property
            android:name="android.window.PROPERTY_XR_ACTIVITY_START_MODE"
            android:value="XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED"
            tools:replace="android:value" />
        ...
    </application>
</manifest>

GDScript で空間コンテナを操作する

OpenXRSpatialContainerExtension シングルトンと OpenXRSpatialContainerState クラスは、XR_EXT_spatial_container 拡張機能と XR_EXT_spatial_container_self_rendering 拡張機能を GDScript に公開します。実行時に OpenXRSpatialContainerExtension を使用して、メインの空間コンテナの状態と境界を検査し、コンテナ信号をリッスンして、BOUNDED モード(3D 境界ボックス)と IMMERSIVE モード(全画面の境界のないビュー)間の遷移をリクエストします。

Spatial Container シグナルに接続する

OpenXRSpatialContainerExtension.is_enabled() を確認して、Spatial Container 拡張機能が現在のデバイスでサポートされ、有効になっていることを確認し、_ready() のコンテナ境界と状態シグナルに接続します。

OpenXRSpatialContainerExtension は、空間コンテナに対して次の状態シグナルを出力します。

  • spatial_container_visibility_changed: コンテナが表示(true)または非表示(false)になったときに、(spatial_container, is_visible) とともに発行されます。is_visible が false の場合は、アニメーション、音声、シミュレーションの更新を一時停止します。
  • spatial_container_interactability_changed: コンテナがユーザー入力フォーカスを取得(true)または喪失(false)したときに、(spatial_container, is_interactive) とともに発行されます。フォーカスが変更されたときに、インタラクティブなハイライト表示と入力処理を有効または無効にします。
  • spatial_container_bounds_mode_changed: コンテナが OpenXRSpatialContainerState.BOUNDED と OpenXRSpatialContainerState.IMMERSIVE の間で切り替わるときに、(spatial_container, bounds_mode) とともに発行されます。環境のビジュアル(スカイボックスやパススルーなど)とモード固有の UI コントロールを切り替える。
func _ready() -> void:
    if OpenXRSpatialContainerExtension.is_enabled():
        OpenXRSpatialContainerExtension.spatial_container_bounds_changed.connect(
            _on_bounds_changed
        )
        OpenXRSpatialContainerExtension.spatial_container_bounds_mode_changed.connect(
            _on_bounds_mode_changed
        )
        OpenXRSpatialContainerExtension.spatial_container_visibility_changed.connect(
            _on_visibility_changed
        )
        OpenXRSpatialContainerExtension.spatial_container_interactability_changed.connect(
            _on_interactability_changed
        )

func _on_visibility_changed(_rid: RID, is_visible: bool) -> void:
    # Pause or resume simulation and audio based on visibility
    pass

func _on_interactability_changed(_rid: RID, is_interactive: bool) -> void:
    # Enable or disable input handling and focus highlights
    pass

3D コンテンツをコンテナの境界に合わせてスケーリングする

BOUNDED モードでは、bounds の最小寸法で 3D コンテンツを均一にスケーリングして、アスペクト比を維持し、常にコンテナの最小側に収まるようにします。IMMERSIVE モードに移行するときに、シーンを 1:1 スケールに復元します。

func _on_bounds_changed(_rid: RID, bounds: Vector3) -> void:
    var uniform_scale: float = min(bounds.x, bounds.y, bounds.z)
    content_root.scale = Vector3.ONE * uniform_scale

func _on_bounds_mode_changed(
    _rid: RID, bounds_mode: OpenXRSpatialContainerState.BoundsMode
) -> void:
    if bounds_mode == OpenXRSpatialContainerState.IMMERSIVE:
        content_root.scale = Vector3.ONE

境界モードと没入モードを切り替える

OpenXRSpatialContainerState.BOUNDED または OpenXRSpatialContainerState.IMMERSIVE を指定して request_main_spatial_container_bounds_mode を呼び出し、境界付き 3D ボリュームと全画面イマーシブ ビューを切り替えます。

# Request transitioning to immersive mode (or pass BOUNDED to return)
OpenXRSpatialContainerExtension.request_main_spatial_container_bounds_mode(
    OpenXRSpatialContainerState.IMMERSIVE
)

関連情報


OpenXR™ および OpenXR ロゴは、The Khronos Group Inc. が所有する商標であり、中国、欧州連合、日本、英国で商標として登録されています。