如果您在 Godot 中有现有的 XR 项目,则无需启动新的单独项目即可添加对 Android XR 的支持。有些步骤是所有项目都必需的,而有些步骤则是可选的,具体取决于项目使用的 XR 功能。在整个步骤中,我们提供了多个已添加对 Android XR 支持的开源 Godot XR 项目的链接,以及展示了启用某些功能所需的更改的相关 pull 请求。
所有项目的必需步骤
无论您的项目支持哪种类型的 XR 功能,都请完成以下主题中的步骤。之后,请查看可选步骤 列表中的功能,以确定您的项目是否需要进行额外的工作。
更新 Godot 和 Godot OpenXR Vendors 插件
请按照以下步骤将您的项目更新到最新的必需版本,并为 Android XR 配置项目的设置:
- 将 Godot 版本更新到 4.6.2 或更高版本。如果您需要有关 项目的其他帮助,请参阅有关 迁移到新版本的文档。
从 Asset Store、Asset Library 或 the repository on GitHub 下载 Godot OpenXR Vendors Plugin 插件 5.1 或更高版本。
为 Android XR 配置项目的设置:
- 为 Android XR 添加导出预设。
- 启用 Use Gradle Build 。
- 在 XR Features 部分中,为 XR Mode 选择 OpenXR, 然后选择 Enable AndroidXR Plugin。
添加对手部跟踪的支持
虽然控制器可能可用,但 Android XR 头戴设备和 XR 眼镜的主要输入方法是手部跟踪。如果可能,您应向 Godot 项目添加手部跟踪支持。
添加对手部跟踪的支持:配置项目设置
首先,请按照以下步骤设置项目设置,以启用手部跟踪及其相关的 OpenXR 扩展程序。
- 打开项目的设置,然后依次前往 General > XR > OpenXR 。
在 Extensions 部分中,选择 Hand Tracking 和 Hand Interaction Profile 。
在 Extensions 部分中找到 Meta 子部分,然后选择 Hand Tracking Mesh 和 Hand Tracking Aim 。
添加对手部跟踪的支持:添加和配置控制器节点
您无需为手部跟踪动态修改现有的 XRController3D 节点,而是添加控制器节点来跟踪和显示手部模型,以及处理来自 Hand Tracking Aim 扩展程序的输入:
向
XROrigin3D节点添加三个额外的XRController3D节点。- 将一个命名为“HandTrackingLeft”,并将跟踪器属性设置为
/user/hand_tracker/left。 - 将另一个命名为“HandTrackingRight”,并将跟踪器属性设置为
/user/hand_tracker/right。 - 将最后一个命名为“HandTrackingAimLeft”,并将跟踪器属性设置为
/user/fbhandaim/left。
如果项目的原始
XRController3D节点命名为“XRController3D_left”和“XRController3D_right”,则场景将如下所示:
- 将一个命名为“HandTrackingLeft”,并将跟踪器属性设置为
将信号
tracking_changedon HandTrackingLeft 和 HandTrackingRight 连接到更新相应控制器追踪器(在前面的 示例中为 XRController3D_left 和 XRController3D_right )可见性的各个函数。例如,连接到 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 Action Map 上设置 Hand Interaction 配置文件
接下来,您将在 OpenXR Action Map 上设置 Hand Interaction 配置文件:
- 打开编辑器底部的 OpenXR Action Map 菜单。
- 删除 Simple Controller 配置文件,以避免与 Galaxy XR 控制器出现兼容性问题。
- 点击 Add Profile ,选择 Hand Interaction ,然后点击 OK 。
您可以随意将此配置文件映射到一个或多个操作集。
根据应用的要求,您可能还需要调整应用处理手部跟踪用户输入的方式。
添加对手部跟踪的支持:为 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 空间中移动界面 元素或对象。为了与这些模式保持一致并提升用户体验,您的应用在使用手部跟踪时,应将捏合注册为与控制器上的按钮按压类似。
如需以这种方式配置应用,请使用您创建的 Hand Interaction 配置文件提供的浮点值来创建虚拟操作:
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 Tools 函数正常运行(例如用于菜单互动的 FunctionPointer),您需要一些额外的代码,以便在用户切换到手部跟踪时交换其正在寻找的操作。
例如,当使用 FunctionPointer 进行菜单互动时,请根据手部跟踪的 XRController3D 节点的
tracking_changed 信号(在前面的 hand
tracking setup steps 中,这些
节点为 HandTrackingLeft 和 HandTrackingRight ),将
active_button_action 属性更新为手部跟踪操作。
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
代码要点
将手部跟踪与人工移动结合使用
如果您的项目使用人工移动,则仍可以支持手部跟踪。例如,您可以构建一个移动系统,让玩家通过手势绘制路径来穿越,也可以让玩家上下挥动手来加速,并使用其他手势进行跳跃、攀爬和滑行。
万物博物馆使用控制器上的 拇指摇杆进行人工移动。手部跟踪移动是通过添加“虚拟拇指摇杆”来实现的,玩家可以通过在空中捏合来触发这些摇杆,并朝着他们希望拇指摇杆移动的方向移动手。
以下是实现此支持的 拉取请求 的一些关键要点:
- 检测到捏合时,系统会实例化
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的原始方向。 - 如需查看使用透视和光照估算的项目完整示例, 请查看 Expedition to Blobotopia 在 GitLab 上。