如果您在 Godot 中已有 XR 專案,可以新增 Android XR 支援,不必另外建立新專案。部分步驟是所有專案的必要步驟,其他步驟則視專案使用的 XR 功能而定。在各個步驟中,我們都加入了多個開放原始碼 Godot XR 專案的連結,這些專案已新增 Android XR 支援功能,以及相關的提取要求,展示啟用特定功能所需的變更。
所有專案都必須完成的步驟
無論專案支援哪種延展實境功能,都請完成下列主題中的步驟。接著,請查看選用步驟清單中列出的功能,判斷專案是否需要額外作業。
更新 Godot 和 Godot OpenXR 供應商外掛程式
請按照下列步驟將專案更新至最新必要版本,並為 Android XR 設定專案設定:
- 將 Godot 版本更新至 4.6.2 以上。如需專案的額外協助,請參閱遷移至新版本的說明文件。
從 Asset Store、Asset Library 或 GitHub 存放區下載 Godot OpenXR Vendors Plugin 5.1 以上版本。
設定 Android XR 專案設定:
- 新增 Android XR 的匯出預設設定。
- 啟用「使用 Gradle 建構」。
- 在「XR Features」部分,選取「XR Mode」的「OpenXR」,然後選取「Enable AndroidXR Plugin」。
新增手勢追蹤支援
Android XR 頭戴式裝置和 XR 眼鏡可能支援控制器,但主要輸入方式是手勢追蹤。如有可能,請在 Godot 專案中加入手部追蹤支援功能。
新增手勢追蹤支援功能:設定專案設定
請先按照下列步驟設定專案,啟用手部追蹤功能和相關的 OpenXR 擴充功能。
- 開啟專案設定,然後依序前往「General」>「XR」>「OpenXR」。
在「擴充功能」部分,選取「手部追蹤」和「手部互動設定檔」。
在「擴充功能」專區中找到「Meta」子專區,然後選取「手勢追蹤網格」和「手勢追蹤瞄準」。
新增手勢追蹤支援功能:新增及設定控制器節點
請勿動態修改現有的 XRController3D 節點以追蹤手部,而是新增控制器節點,追蹤及顯示手部模型,並處理手部追蹤瞄準擴充功能的輸入內容:
在
XROrigin3D節點中新增三個XRController3D節點。- 將其中一個命名為「HandTrackingLeft」,並將追蹤器屬性設為
/user/hand_tracker/left。 - 將另一個「HandTrackingRight」命名,並將追蹤器屬性設為
/user/hand_tracker/right。 - 將最後一個命名為「HandTrackingAimLeft」,並將追蹤器屬性設為
/user/fbhandaim/left。
如果專案的原始
XRController3D節點名為「XRController3D_left」和「XRController3D_right」,場景看起來會像這樣:
- 將其中一個命名為「HandTrackingLeft」,並將追蹤器屬性設為
-
舉例來說,與 HandTrackingLeft 訊號連結的函式可能如下所示:
func _on_hand_tracking_left_hand_tracking_changed(tracking): $XROrigin3D/XRController3D_left.visible = not tracking 在手勢追蹤控制器節點上啟用「Show When Tracked」(在追蹤時顯示) 屬性。
現在,專案可以根據使用者是否使用手勢追蹤或控制器,在控制器模型和手勢追蹤模型之間切換。
將一些
OpenXRFbHandTrackingMesh節點新增為手勢追蹤控制器節點的子項。將
XRHandModifier3D節點新增為這些OpenXRFbHandTrackingMesh節點的子項,並確保已設定正確的「手勢追蹤」Hand Tracker屬性,以便將即時手勢追蹤資料套用至模型。
新增手勢追蹤支援:在 OpenXR 動作對應中設定手部互動設定檔
接著,您會在 OpenXR 動作對應中設定「手部互動」設定檔:
- 開啟編輯器底部的「OpenXR Action Map」選單。
- 刪除「Simple Controller」設定檔,避免與 Galaxy XR 控制器發生相容性問題。
- 按一下「新增設定檔」,選取「手部互動」,然後按一下「確定」。
隨意將這個設定檔對應至一或多個動作集。
視應用程式需求而定,您可能也想調整應用程式如何透過手勢追蹤處理使用者輸入內容。
新增手勢追蹤支援:設定 Android XR 的選單手勢
最後,您可以為 Android XR 實作選單手勢。當玩家的左手處於可執行選單手勢的正確位置時,系統會顯示圖示,並在使用者執行手勢時顯示或隱藏選單。您將使用先前新增的 HandTrackingAimLeft 節點處理這項作業。
在左側手勢追蹤節點中新增廣告看板四邊形,顯示您選擇的圖示 (請參閱下圖中先前新增的控制器節點中的 MenuIcon 節點)。
將 HandTrackingAimLeft 上的
button_pressed和button_released訊號連結至這類函式:@onready var menu_icon: MeshInstance3D = $XROrigin3D/HandTrackingLeft/MenuIcon func _on_hand_tracking_aim_left_button_pressed(p_name): if p_name == "menu_pressed": toggle_menu() elif p_name == "menu_gesture": if OS.has_feature("androidxr"): menu_icon.visible = true func _on_hand_tracking_aim_left_button_released(p_name): if p_name == "menu_gesture": menu_icon.visible = false
特定功能的選用步驟
完成專案的必要步驟後,您可以根據應用程式的需求和功能,決定是否需要為特定功能執行額外作業。如要進一步瞭解各項選用功能,請參閱下列章節。
將雙指併攏動作註冊為按鈕按下動作
在 Android XR 中,雙指撥動可用於許多基礎系統動作,例如選取項目、捲動、移動或調整視窗大小,以及在 2D 和 3D 空間中移動 UI 元素或物件。為配合這些模式並提供一致的使用者體驗,使用手勢追蹤功能時,應用程式應以類似於控制器按鈕按壓的方式註冊捏合動作。
如要以這種方式設定應用程式,請使用您建立的「手部互動」設定檔提供的浮點值,建立虛擬動作:
const PRESSED_THRESHOLD := 0.8
const RELEASED_THRESHOLD := 0.6
@onready var left_controller: XRController3D = $XROrigin/XRController3D_left
func _on_xr_controller_3d_left_input_float_changed(p_name: String, value: float):
if p_name == "pinch":
var xr_tracker = XRServer.get_tracker(left_controller.tracker)
if _left_hand_pinching:
if value < RELEASED_THRESHOLD:
_left_hand_pinching = false
xr_tracker.set_input("pinch_pressed", false)
else:
if value > PRESSED_THRESHOLD:
_left_hand_pinching = true
xr_tracker.set_input("pinch_pressed", true)
程式碼重點
- 檢查
float值是否大於或小於XRController3Dinput_float_changed信號中的特定門檻。 - 建立名為
pinch_pressed的虛擬動作。
搭配手勢追蹤功能使用 XR Tools 函式
許多 Godot XR 專案都會使用 Godot XR Tools,包括這個頁面中連結的部分開放原始碼專案。如要讓部分 XR 工具函式 (例如選單互動的 FunctionPointer) 運作,您需要一些額外程式碼,在使用者切換至手勢追蹤時,交換要尋找的動作。
舉例來說,使用 FunctionPointer 進行選單互動時,請根據手勢追蹤的 XRController3D 節點 tracking_changed 信號,將 active_button_action 屬性更新為手勢追蹤動作 (在先前的手勢追蹤設定步驟中,這些節點為 HandTrackingLeft 和 HandTrackingRight)。
const TRIGGER_POINTER_ACTION = "trigger_click"
const PINCH_POINTER_ACTION = "pinch_pressed"
@onready var func_point_left: XRToolsFunctionPointer = %FunctionPointerLeft
func _on_hand_tracking_left_tracking_changed(tracking: bool) -> void:
if tracking:
func_point_left.active_button_action = PINCH_POINTER_ACTION
else:
func_point_left.active_button_action = TRIGGER_POINTER_ACTION
程式碼重點
- 這段程式碼會依據
pinch_pressed虛擬動作,您可以建立該動作,將雙指撥動註冊為按鈕按下動作。
搭配人工移動功能使用手勢追蹤功能
如果專案使用人工移動,仍可支援手勢追蹤。舉例來說,您可以建立移動系統,讓玩家透過手勢繪製路徑來移動,也可以讓玩家上下擺動雙手來加速,並使用其他手勢跳躍、攀爬和滑翔。
萬物博物館:使用控制器上的拇指桿進行人工移動。手勢追蹤移動功能是透過新增「虛擬搖桿」實作,玩家只要在空中捏合手指即可觸發,並將手移往搖桿要移動的方向。
以下是實作這項支援功能的提取要求的一些重要事項:
- 偵測到雙指撥動時,系統會例項化
XRVirtualThumbstick場景。 - 按住雙指時,系統會將與原始雙指位置的相對距離和方向轉換為
Vector2,並虛擬對應至一般搖桿輸入。 - 系統也會以兩個廣告牌四邊形網格的形式,向玩家提供這項輸入內容的視覺回饋,說明搖桿位置。
您可以嘗試類似方法,盡可能減少變更,讓現有的搖桿驅動移動程式碼正常運作。不過,您的專案可能仍需要自訂手勢追蹤的移動解決方案。
新增直通支援
您可以在應用程式中加入透視支援,讓使用者看到現實世界周遭環境。
如要為應用程式執行這項操作,請進行下列程式碼變更:
- 將 OpenXR
XRInterface的environment_blend_mode設為XR_ENV_BLEND_MODE_ALPHA_BLEND。 - 將
WorldEnvironment節點的background_mode設為BG_COLOR。 - 將
WorldEnvironment節點的background_color設為完全透明的顏色。 - 將
Viewport transparent_bg屬性設為true。
使用光線估計擴充功能
啟用透視功能時,請考慮使用 Android XR Light Estimation OpenXR 擴充功能。這項擴充功能會調整 WorldEnvironment 和 DirectionalLight3D 的屬性,更貼近使用者現實環境的光線,讓虛擬物體更融入現實世界的光線條件。您可以在專案設定中啟用這項擴充功能。
- 開啟專案設定,然後依序前往「General」>「XR」>「OpenXR」。
在「Androidxr」部分中,選取「Light Estimation」。
在場景樹狀結構中新增
OpenXRAndroidLightEstimation節點,並將其連結至場景的WorldEnvironment和DirectionalLight3D。
示例:啟用或停用穿透和光線估算功能
下列程式碼會啟用或停用直通和光線估算功能:
@onready var world_environment = $WorldEnvironment
@onready var directional_light = $DirectionalLight3D
@onready var directional_light_orig_transform: Transform3D = directional_light.transform
func set_passthrough_enabled(p_enabled: bool) -> void:
var xr_interface = XRServer.find_interface("OpenXR")
if xr_interface == null:
return
var supported_blend_modes = xr_interface.get_supported_environment_blend_modes()
if not supported_blend_modes.has(XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND):
return
# Passthrough
if p_enabled:
xr_interface.set_play_area_mode(XRInterface.XR_PLAY_AREA_STAGE)
xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND
world_environment.environment.background_mode = Environment.BG_COLOR
world_environment.environment.background_color = Color(0.0, 0.0, 0.0, 0.0)
get_viewport().transparent_bg = true
else:
xr_interface.set_play_area_mode(XRInterface.XR_PLAY_AREA_ROOMSCALE)
xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_OPAQUE
world_environment.environment.background_mode = Environment.BG_SKY
get_viewport().transparent_bg = false
# Light Estimation
if OS.has_feature("androidxr"):
var light_estimation = Engine.get_singleton("OpenXRAndroidLightEstimationExtension")
if p_enabled and light_estimation.is_light_estimation_supported():
light_estimation.start_light_estimation()
elif light_estimation.is_light_estimation_started():
light_estimation.stop_light_estimation()
directional_light.transform = directional_light_orig_transform
程式碼重點
- 停用光線估算功能時,必須手動還原
DirectionalLight3D的原始方向。 - 如需使用 Passthrough 和光線估算功能的完整專案範例,請參閱 GitLab 上的 Expedition to Blobotopia。