空間容器可讓應用程式在全螢幕模式下,於系統管理的 3D 體積定界框內算繪 3D OpenXR 內容,或在執行階段轉換為全螢幕無邊界體驗。
請按照這份指南,在專案中設定及使用空間容器。

空間容器的運作方式
在專案設定中啟用空間容器後:
- 整個 3D 場景會放在單一主要空間容器中,並以場景原點
(0, 0, 0)為中心。您不需要標記或指派個別Node3D節點,即可將其放入容器中。 - 應用程式會使用專案設定中的邊界模式 (
Bounded或Immersive) 和初始邊界尺寸,啟動至受管理的完整空間模式。在有界模式下,系統會自動裁剪場景中超出定界框尺寸的任何 3D 幾何圖形。 - 根據預設,Android XR 系統會提供視窗控制項,讓使用者在 3D 空間中抓取、移動及重新定位有界容器,或將其最小化及關閉。在執行階段,應用程式可以調整容器大小、在有界模式 (
OpenXRSpatialContainerState.BOUNDED) 和全螢幕沉浸模式 (OpenXRSpatialContainerState.IMMERSIVE) 之間切換,並使用OpenXRSpatialContainerExtension單例模式回應邊界和狀態變更。
必要條件
開始之前,請確認開發環境和目標裝置符合下列需求:
- Godot 版本:Godot 4.8-dev 以上版本。
- 專案設定:完成 Godot Engine 專案設定指南中的所有步驟。
- Godot OpenXR Vendors Plugin:安裝 5.2 以上版本的 Godot OpenXR Vendors Plugin,即可支援 Android XR 專屬擴充功能。
- 目標裝置:支援 Spatial API 級別 4 以上版本的 Android XR 裝置。在執行階段呼叫
OpenXRSpatialContainerExtension.is_enabled(),確認裝置是否支援擴充功能。
在專案設定中啟用空間容器
調整專案設定,啟用 OpenXR、空間容器、自動執行階段權限,以及 Alpha 混合穿透模式:
- 依序開啟「Project」>「專案設定」。
- 在「專案設定」視窗的右上角,啟用「Advanced Settings」切換鈕。
- 依序前往「General」>「XR」>「Shaders」,然後選取「Enabled」。
- 依序前往「General」>「XR」>「OpenXR」,然後調整下列設定:
- 選取「Enabled」,為專案啟用 OpenXR。
- 將「Environment Blend Mode」設為「Alpha Blend」。
- 同樣在「OpenXR」下方,前往「Extensions」部分,並進行下列設定:
- 選取「Automatically Request Runtime Permissions」,應用程式就會在啟動時,自動提示使用者授予 Android 資訊清單中宣告的 XR 執行階段權限。
- 在「Spatial Container」子節下方,選取「Enabled」。
- 將「Bounds Mode」設為「Bounded」,即可在 3D 定界框中啟動,或設為「Immersive」,即可在全螢幕沉浸模式中啟動。
- 將「Bounds」設為初始寬度、高度和深度尺寸 (以公尺為單位),例如
Vector3(1.0, 1.0, 1.0)。
- 依序前往「General」>「Rendering」>「Viewport」,然後選取「Transparent Background」。
設定 Android 匯出、權限和全螢幕模式
接著,請設定 Android 匯出預設、權限和活動啟動模式,讓應用程式在全螢幕模式下執行,並啟用空間容器。
設定 Android 匯出預設設定
- 依序前往「Project」>「Export...」,然後選取「Android」匯出預設設定。
在「Gradle Build」下方,選取「Use Gradle Build」,並將「Min SDK」設為
34以上。
在「XR Features」下方,將「XR Mode」設為「OpenXR」,然後選取「Enable AndroidXR Plugin」。
在「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:
依序點選「Project」>「Export...」> Android,依序前往「Permissions」>「Custom Permissions」,然後新增
android.permission.SCENE_UNDERSTANDING_COARSE。在「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/build/AndroidManifest.xml,使用「Project」>「Install Android Build Template...」安裝) 中,為 Android 活動宣告 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 類別會向 GDScript 公開 XR_EXT_spatial_container 和 XR_EXT_spatial_container_self_rendering 擴充功能。在執行階段,使用 OpenXRSpatialContainerExtension 檢查主要空間容器的狀態和邊界、監聽容器信號,並要求在 BOUNDED 模式 (3D 定界框) 和 IMMERSIVE 模式 (全螢幕無邊界檢視畫面) 之間切換。
連結至空間容器信號
檢查 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 標誌是 Khronos Group Inc. 擁有的商標,並已在中國、歐盟、日本和英國註冊為商標。