Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

XR 动作映射

Godot 的 XR 系统里包含一个动作映射(action map)功能。目前,这个系统属于 OpenXR 模块的一部分。不过,我们计划在不久的将来把 WebXR 也纳入进来,所以在本篇文档中,我们统一称之为‘XR 动作映射系统’。它基本上就是原原本本地实现了 OpenXR 自带的动作映射系统。

XR 动作映射系统负责将 XR 手柄的输入、位置数据以及输出(比如震动反馈)提供给你的游戏或应用程序。它实现这一点的方式是:暴露一系列可以为你游戏量身定制的‘命名动作’,然后将这些动作绑定到你 XR 设备上实际的输入和输出上。

由于 XR 动作映射目前是 OpenXR 模块的一部分,因此需要在项目设置中启用 OpenXR 才能显示它:

../../_images/openxr_enabled.webp

然后,你会在屏幕底部看到 XR 行动地图界面:

../../_images/xr_action_map.webp

备注

Godot 内置的输入系统和 XR 动作映射系统其实有很多共同点。事实上,我们最初的想法确实是在现有的输入系统上直接增加功能,然后把数据暴露给 OpenXR 动作映射系统。我们未来或许会重新审视这个想法,但事实证明,当时需要克服的问题实在太多了。仅举几个例子来说:

  • Godot 的输入系统主要是围绕按键输入(button inputs)设计的,而 XR 则引入了扳机键(triggers)、轴(axis)、空间姿态(poses)以及触觉反馈(haptics,属于输出功能)等额外元素。如果把这些全都加进来,会极大地增加输入系统的复杂度,而且这些功能要么在普通控制器上根本用不了,要么就与现有的设计思路相冲突。因此,团队认为这样做反而会让大多数 Godot 用户感到困惑。

  • Godot 的输入系统是基于原始输入数据(raw input data)运作的,这些数据经过解析后会触发相应的动作。并且,这些原始数据是直接向终端用户开放的。而 OpenXR 则完全不同,它把所有的原始数据都隐藏了起来,并替我们完成了所有的解析工作,我们只能获取到已经解析好的动作数据。这种不一致性很可能会带来隐患——如果一位不知情的用户尝试把 XR 设备当作普通的输入设备来使用,就非常容易引发 Bug。

  • Godot 的输入系统允许在运行时更改输入与操作的绑定,而 OpenXR 则不允许。

  • Godot 的输入系统基于设备 ID,而这在 OpenXR 中毫无意义。

这确实意味着混合了传统输入和 XR 控制器的游戏/应用将会有一个分离。对于大多数应用来说,要么使用一个,要么使用另一个,这不被视为问题。最后,这是系统的限制。

默认动作映射

如果找不到操作映射文件,Godot 会自动创建默认操作映射。

警告

这个默认的动作映射最初是为了帮助开发者把他们的 XR 游戏或应用从 Godot 3 引擎迁移到 Godot 4 而设计的。正因如此,这个映射基本上就是把所有默认支持的控制器上已知的输入按键,和动作进行了一对一的简单绑定。这并不是一个设置动作映射的好范例。不过,它确实能让刚接触 Godot XR 的新手开发者有一个可以上手的起点,也省去了他们一开始就必须先为自己的游戏或应用精心设计一套完整动作映射的麻烦。

在这个入门教程里,我们将从一个空白的动作映射(action map)开始。你可以点击顶部的垃圾桶图标,把“Godot action set”这一项删掉。这样就能清空所有的动作。另外,你可能还想顺手把那些暂时不打算设置的控制器先移除掉,关于这一点,我们稍后会详细说明。

动作集

备注

在我们正式开始之前,你会在本文档中频繁看到“XR runtime(XR 运行时)”这个词。我们所说的 XR 运行时,指的是用来控制 AR 或 VR 头显,并与其进行交互的软件。然后,XR 运行时会通过像 OpenXR 这样的 API(应用程序接口)将这些功能开放给我们使用。所以:

  • 对于 Steam,这是 SteamVR,

  • 对于桌面上的 Meta,这是 Oculus 客户端(包括使用 Quest link 时),

  • 对于 Quest 上的 Meta,这是 Quest 的本地 OpenXR 客户端,

  • 在 Linux 上,这可能是 Monado 等。

行动地图允许我们组织我们的行动。每组都可以单独启用或禁用。

这里的概念是,在不同的场景中,可以有不同的集合来提供绑定。你可以:

  • 比如,当你正在四处走动时,就启用一个 Character control (角色控制)动作集,

  • 比如,当你正在驾驶载具时,就启用一个 Vehicle control (载具控制)动作集,

  • 比如,当菜单打开时,就启用一个 Menu (菜单)动作集。

这样,你就能确保只开启当前游戏(或应用)状态下真正需要的那个动作集。

如果你打算把控制器上的同一个输入按键绑定到不同的动作上,这一点就显得尤为重要。举个例子:

  • 在你的 Character control (角色控制)动作集里,可能会有一个名为 Jump (跳跃)的动作,

  • 在你的 Vehicle control (载具控制)动作集里,可能会有一个名为 Accelerate (加速)的动作,

  • 比如,在你的 Menu (菜单)动作集里,可能会有一个名为 Select (选择)的动作。

它们全部都绑定到了你手柄的扳机键上。

OpenXR 只会把一个输入或输出绑定到单个动作上。如果同一个输入或输出被绑定到了多个动作上,那么只有处于激活状态、且优先级最高的那个动作集里的动作会被更新和使用。因此,在我们上面的例子中,确保只有一个动作集处于激活状态就显得非常重要。

对于你的第一个 XR 游戏/应用程序,我们强烈建议只从一个动作集开始,不要过度设计。

所以在本文的教程里,我们将创建一个名为 my_first_action_set 的单一动作集。我们只需要点击 Add action set (添加动作集)按钮就可以完成这一步:

../../_images/xr_my_first_action_set.webp

我们表格中的各列内容如下:

Col

描述

1

my_first_action_set

这是动作集的内部名称。除了长度限制之外,OpenXR 并没有对这个名称规定具体的限制。不过,有些 XR 运行时可能会不太喜欢名称里包含空格或特殊字符。

2

我的第一套动作

这是动作集的可读名称。一些 XR 运行时会向最终用户显示这个名称,例如在配置对话框中。

3

0

这是动作集的优先级。如果多个处于激活状态的动作集,都将动作绑定到了同一个手柄的输入或输出上,那么优先级数值最高的那个动作集将胜出,并决定最终哪个动作会被更新。

动作

在 XR 动作映射中,‘动作(Action)’就是你的游戏或应用程序实际交互的对象。举个例子,我们可以定义一个名为 Shoot (射击)的动作。那么,绑定到这个动作上的输入(比如扣动扳机),就会触发场景中对应 XRController3D 节点上的 button_pressed 信号,并且这个信号会携带一个 name 参数,其值就是 Shoot

你也可以主动去查询(poll)某个动作的当前状态。比如,. XRController3D 节点就自带一个 is_button_pressed 方法,可以用来检查按钮当前是否被按下。

动作可以用于输入和输出,每个动作都有一个类型,用于指定其行为。

  • Bool 类型用于离散输入,例如按键。

  • Float 类型用于模拟输入,例如触发器。

这两者的特别之处在于它们是唯一可以互换的动作。OpenXR 会处理 BoolFloat 输入或动作之间的转换。可以通过调用 XRController3D 节点上的方法 get_float 来获得一个 Float 类动作的值。此值更改的时候会发出 input_float_changed 信号。

备注

以按键查询模拟输入时会应用一个阈值。该阈值目前由 XR 运行时专门管理。未来有计划对 Godot 进行扩展,为这些阈值提供某种程度上的控制。

Vector2 类型将输入定义为轴输入。触摸屏,操纵杆等类似输入都以向量形式显示。可以通过在 XRController3D 节点上调用 get_vector2 方法来获取 Vector2 类动作的值。当发生更改时,它会发出 input_vector2_changed 信号。

Pose (姿态)类型定义了一个经过空间追踪的输入。在 OpenXR 中,有多种可用的 "姿态" 输入,比如: aim (瞄准)、 grip (握持)和 palm (手掌)。你的 XRController3D 节点会自动根据该节点 pose 属性所分配的姿态动作来进行定位。关于姿态的更多细节,我们稍后会详细讲解。

备注

Godot 中的 OpenXR 实现还提供了一个名为 Skeleton (骨骼)的特殊姿态。这是手部追踪(Hand Tracking)实现的一部分。这个姿态是通过 skeleton 动作来提供的,它不受常规动作映射(Action Map)系统的限制。因此,只要设备支持手部追踪,这个功能就会一直存在。你不需要像其他动作那样去特意绑定它,就能直接使用。

最后,目前唯一的输出类型就是 Haptic (触觉反馈)。它允许我们设定触觉反馈的强度,比如控制手柄的振动。手柄可以拥有多个触觉输出通道,而且 OpenXR 也正在逐步加入对触觉反馈背心(Haptic Vests)的支持。

那么,咱们来给‘瞄准姿态(aim pose)’添加一个动作吧。操作很简单,只需要点击动作集(action set)旁边的 + 号按钮就行了:

../../_images/xr_aim_pose.webp

我们表格中的各列内容如下:

Col

描述

1

aim_pose

这是该动作的内部名称。除大小外 OpenXR 不明确指定对该名称的任何限制,但某些 XR 运行时会排斥空格或特殊字符。

2

瞄准姿势

这是该动作的人类可读名称。某些 XR 运行时会将该名称显示给终端用户,例如在配置窗口中。

3

姿势

主题类型变种。

OpenXR 定义了许多控制器常用的可绑定输入姿态。对于不同的控制器支持哪些姿势,没有规则。OpenXR 目前定义的姿势有:

  • 在大多数手柄上,‘瞄准姿态(aim pose)’被定位在手柄前方一点点的位置,并且朝向正前方。这个姿态非常适合用来做激光瞄准器,或者用来对齐武器的枪口。

  • 在大多数手柄上,‘握持姿态(grip pose)’的位置被设定在手柄握键(grip button)所在的地方。但这个姿态的朝向在不同手柄之间会有所不同,甚至对于同一个手柄,在不同的 XR 运行时上也可能存在差异。

  • 在大多数手柄上,‘手掌姿态(palm pose)’被定位在握住手柄的手掌中心位置。这是一个全新的姿态,目前并不是所有的 XR 运行时都支持它。

备注

如果使用手部跟踪,目前不同 XR 运行时之间的实现存在很大差异。因此,动作图目前不适合手部跟踪。这方面的工作正在进行中,敬请关注。

让我们完成一个非常简单的射击游戏/应用程序的动作列表:

../../_images/xr_all_actions.webp

我们添加的操作有:

  • 移动,它允许用户在常规的物理空间追踪范围之外进行移动。

  • 抓取,检测用户想要拿东西。

  • 射击,它检测到用户想要发射他们持有的武器。

  • 触觉,它允许我们输出触觉反馈。

现在请注意,我们在当前阶段并没有去区分左手和右手。左右手的区分是在下一个阶段才确定的。我们把动作系统实现成了这样一种模式:你可以把同一个动作同时绑定到双手上,然后由合适的 XRController3D 节点来负责发射相应的信号。

警告

对于‘抓取’和‘射击’这两个动作,我们都使用了 Bool (布尔值)类型。就像前面提到的那样,OpenXR 确实会自动把模拟量按键(比如扳机键)转换成布尔值,但目前并不是所有的 XR 运行时都能给出一个合理的触发阈值。

我们建议采取一个变通方法:在与扳机键(Triggers)和握键(Grip buttons)交互时,改用 Float (浮点数)类型,然后自己设定一个触发阈值。

对于像 A/B/X/Y 这种没有模拟量选项的按键,使用 Bool (布尔值)类型就非常合适。

备注

你可以在同一个配置文件(Profile)中,把同一个动作绑定到同一个手柄的多个不同输入上。在这种情况下,XR 运行时会尝试将这些输入信号合并起来。

  • 对于 Bool (布尔值)输入,系统会对这些按键执行一个‘逻辑或( OR )’运算。

  • 对于 Float (浮点数)输入,系统会取所有已绑定输入中的最大值。

  • Pose (姿态)输入的行为是未定义的,但系统很可能会使用最先绑定的那个输入。

你不应该把同一个动作集(Action Set)里的多个动作,绑定到同一个手柄输入信号上。如果你这么做了,或者你从多个动作集里绑定了动作,但它们之间的优先级发生了重叠,那么程序的行为将会变得无法预测(未定义)。XR 运行时可能会直接拒绝接受你的动作映射表,也可能会简单地按照‘先到先得’的原则来处理。

我们仍在研究将多个动作绑定到同一个输出的限制,因为这种场景是有意义的。OpenXR 规范似乎不允许这样做。

既然我们已经定义了基本的动作,那么是时候把它们连接起来了。

配置文件

在 OpenXR 里,手柄的按键绑定通常被称作 "交互配置文件(Interaction Profiles)" 。不过我们把它简写成了 "配置文件(Profiles)" ,纯粹是因为这样写占用的空间更小一点。

选择这个通用名称是因为控制器不能覆盖整个系统。目前也有跟踪器、遥控器和跟踪笔的配置文件。对于跑步机、触觉背心等设备也有规定,尽管这些还不是规范的一部分。

警告

要知道 OpenXR 对支持的设备有严格的检查,这一点很重要。核心规范确定了许多控制器和类似设备及其支持的输入和输出。每个 XR 运行时都必须接受这些交互配置文件,即使它们不适用。

新设备是通过扩展添加的,XR 运行时必须指定它们支持哪些设备。不支持通过扩展添加的设备的 XR 运行时将不接受这些配置文件。不支持添加的输入或输出类型的 XR 运行时通常会崩溃。

正因如此,Godot 会保留所有可用设备的元数据(meta data),包括它们的输入、输出信号,以及是由哪个扩展(extension)来提供支持。你可以为你想要支持的所有设备创建交互配置文件,而 Godot 会自动过滤掉那些用户当前使用的 XR 运行时并不支持的设备。

这意味着为了支持新的设备,你可能需要升级到最新版本的Godot。

不过同样重要的是,大家要知道,我们的动作映射系统在设计之初就已经把这种情况考虑在内了。当市面上推出了新的设备,或者你的用户在使用一些你手头并没有的硬件时,动作映射系统就会依赖 XR 运行时来发挥作用。这时候,XR 运行时的职责就是去挑选一个最匹配的交互配置文件,并自动把它适配到用户正在使用的这款手柄上。

XR 运行时如何做到这一点取决于运行时的实现,因此运行时之间有很大的差异。一些运行时甚至允许用户自己编辑绑定。

运行时的一个常见做法是,首先去寻找有没有完全匹配的交互配置文件。如果没找到,它就会去检查像 "Touch 手柄" 这类最常见的配置文件,并尝试进行转换。如果以上方法都行不通,它最后就会退而求其次,去检查通用的: "Simple controller"

备注

这里有一个非常重要的结论:当系统检测到手柄,并将动作映射(action map)应用到它上面时,XR 运行时的行为并不会被完全限制在你在 Godot 动作映射编辑器中设置的那些具体配置里。虽然运行时通常会基于你在动作映射中设置的某个绑定来选择一个合适的映射方案,但它也可能会偏离(或不完全照搬)你的原始设置。

例如,当使用触摸控制器配置文件时,以下任何一种情况都可能发生:

  • 我们可能在使用 Quest 1 控制器,

  • 我们可能在使用 Quest 2 控制器,

  • 我们可以使用 Quest Pro 控制器,但没有提供 Quest Pro 配置文件,或者使用的 XR 运行时不支持 Quest Pro 控制器,

  • 它可能是一个完全不同的控制器,没有给出配置文件,但是 XR 运行时使用触摸绑定作为基础。

因此,目前没有办法确切地知道用户实际使用的是哪个控制器。

警告

最后,这让很多人犯了错误,绑定并不是一成不变的。XR 运行时允许用户定制绑定是完全允许的,甚至是可以预期的。

目前,没有一个 XR 运行时提供这种功能,尽管 SteamVR 有一个来自 OpenVRs action map system 的现有 UI ,仍然可以访问。不过,这方面的工作正在积极进行中。

第一个控制器绑定

让我们以触摸控制器为例,设置我们的第一个控制器绑定。

点击 "添加配置文件(Add profile)",找到 Touch 手柄控制器,然后把它添加进来。如果在列表里没找到它,那可能是因为它已经被添加过了。

../../_images/xr_add_touch_controller.webp

现在我们的用户界面(UI)上会同时显示出左手和右手手柄的面板。这些面板里包含了每个手柄所有可能的输入和输出信号。我们可以点击每个条目旁边的 + 号,来把它绑定到一个具体的动作上:

../../_images/xr_select_action.webp

引擎配置:

../../_images/xr_touch_completed.webp

每一个动作都绑定了给定的输入或输出,并且涵盖了左右两个手柄,这表明我们支持在任意一个手柄上触发该动作。不过,‘移动(movement)’动作是个例外,它只绑定了右手手柄。因为我们很可能会想把左手摇杆用在别的地方,比如用来实现传送(teleport)功能。

在开发你的游戏或应用时,你必须考虑到这样一种可能性:用户可能会更改按键绑定,把移动操作绑定到左手的摇杆上。

另外请注意,我们的‘射击(shoot)’和‘抓取(grab)’这两个布尔型(boolean)动作,目前关联的是 Float (浮点型)类型的输入。正如前面提到的,OpenXR 会自动在这两种类型之间进行转换,但请务必仔细阅读本文档前文关于这一点给出的警告。

备注

有些输入信号在我们的列表里似乎出现了好几次。

比如,我们会发现 X 按钮出现了两次,一次是 X click (按压),另一次是 X touch (触摸)。这是因为 Touch 手柄配备了电容式传感器。

  • X touch (X 键触摸):如果用户只是轻轻碰了一下 X 键,该值就会为 true(真)。

  • X click (X 键按压):当用户真正按下这个按钮时,该值会为 true(真)。

同样的道理,对于摇杆,我们也有:

  • Thumbstick touch (摇杆触摸):如果用户的手指触碰到了摇杆,该值就会为 true(真)。

  • Thumbstick (摇杆):它会返回一个数值,用来表示摇杆被推向的方向。

  • Thumbstick click (摇杆按压):当用户把摇杆按下去时,该值为 true(真)。

需要特别注意的是,只有少数几款 XR 手柄才支持触摸感应,或者在摇杆上带有按压(click)功能。在设计你的游戏或应用时,请务必牢记这一点。一定要确保这些功能只作为游戏或应用的‘可选功能’来使用。

简单控制器

"简易控制器"(Simple Controller)是 OpenXR 提供的一种通用备用控制器。接下来,我们将对它应用我们的按键映射方案:

../../_images/xr_simple_controller.webp

很明显,‘简易控制器’的功能实在是太简陋了。除了那些最简单的 VR 游戏或应用,它在其他任何稍微复杂点的场景里都根本不够用。

正因如此,许多 XR 运行平台(runtime)只会在万不得已时,才会启用这个简易控制器。它们通常会优先尝试使用那些主流系统(比如 Oculus Touch 等)的按键绑定,作为首选的备用方案。

备注

由于‘简易控制器’(Simple Controller)大概率无法满足你游戏的实际需求,开发者很容易产生一种冲动,想要去为 OpenXR 支持的每一个手柄都提供专门的按键绑定。而默认的动作映射表(action map)看起来似乎也在暗示,这么做是一条可行的路子。但正如我们之前提到的,这个默认的动作映射表其实主要是为了方便从 Godot 3 迁移过来而设计的。

OpenXR 工作组的建议是:开发者只应该去设置那些自己实际测试过的手柄的按键绑定。XR 运行平台(runtime)在设计时就已经充分考虑到了这一点。它们在进行按键重映射时,往往比开发者靠推测做出的判断要准确得多。尤其是因为开发者根本无法亲自测试,自己瞎猜出来的映射方案到底能不能让最终用户获得舒适的体验。

这也是我们给出的建议:将你的动作映射表(action map)限制在你实际测试过游戏的设备交互配置文件(interaction profiles)范围内。很多运行平台(runtime)都会广泛使用 Oculus Touch 控制器作为通用的备用控制器。如果你能使用 Meta Rift 或 Quest 来测试游戏,并添加这个配置文件,那么你的游戏大概率也能在其他头显上正常运行。

绑定修改器

动作映射的主要目标之一,就是让应用程序(比如游戏)不再需要去关心底层到底用了什么硬件。但在某些情况下,不同硬件之间客观存在的物理差异,要求我们必须对输入信号进行一些‘按键绑定’之外的额外调整。这种需求五花八门,小到设置输入阈值,大到直接改变控制器上可用的输入项。

绑定修饰器默认是未启用的,需要在 OpenXR 的项目设置中手动开启。另外,并不能保证所有的运行平台(runtime)都支持这些修饰器。你需要查阅你所针对平台的官方支持文档,然后自行决定是直接依赖这些修饰器,还是实现某种备用方案(fallback mechanism)以防万一。

如果你的目标平台(runtime)有多个,并且它们都支持同一款手柄,那你可能需要为每个平台单独创建一套动作映射表(action map)。你可以通过为每个平台使用不同的导出模板(export templates),并配合一个自定义的 feature tag ,来指定 Godot 到底该使用哪一套动作映射表。

在 Godot 中,绑定修饰器分为两大类:一类是作用于整个交互配置文件(interaction profile)层面的修饰器,另一类则是作用于单个绑定(individual bindings)的修饰器。

交互配置文件上的绑定修饰器

如果想添加应用于整个交互配置文件(interaction profile)的绑定修饰器,你可以通过点击交互配置文件编辑器右侧的‘修饰器’按钮来访问。

../../_images/openxr_ip_binding_modifier.webp

你只需要点击‘添加绑定修饰器’( Add binding modifier )按钮,就可以添加一个新的修饰器啦。

警告

由于 Godot 无法提前预知哪些控制器和运行环境支持特定的修饰器,因此系统不会对添加修饰器做任何限制。如果遇到不支持的修饰器,它们会被直接忽略。

方向键绑定修饰器

方向键(dpad)绑定修饰器会为当前控制器上的每一个摇杆(joystick)和触控板(thumbpad)输入,在交互配置文件(interaction profile)中增加新的输入项。它会将这些原本的输入转变为一个方向键,并分解成上、下、左、右四个独立的输入,最终以按钮的形式呈现出来。

../../_images/openxr_thumbstick_dpad.webp

备注

与扩展功能相关的输入项,都会用星号(*)来标记。

如果想要使用方向键(dpad)绑定修饰器,你需要先在项目设置(project settings)中启用该扩展功能:

../../_images/openxr_project_settings_dpad_modifier.webp

只要启用该扩展,就能直接通过默认设置让这项功能正常工作。

添加修饰器是可选的,它允许你微调方向键(dpad)功能的具体表现方式。你可以多次添加修饰器,从而为不同的输入源设置不同的参数。

../../_images/openxr_dpad_modifier.webp

这些设置的用途如下:

  • Action Set (动作集)用于指定当前这些设置将会应用到哪一个具体的动作集上。

  • Input Path (输入路径)用于定义被映射到这些新方向键(dpad)输入上的原始输入源。

  • Threshold (按下阈值)用于指定一个数值,当达到或超过这个数值时,方向键动作就会被启用(也就是判定为按下)。举个例子,如果把这个值设为 0.6 ,那就意味着:一旦摇杆或触控点距离中心点的距离超过 0.6 ,系统就会判定该方向键动作被按下了。

  • Threshold Released (释放阈值)用于指定一个数值,当低于这个数值时,方向键动作就会被禁用(也就是判定为松手)。举个例子,如果把这个值设为 0.4 ,那就意味着:一旦摇杆或触控点距离中心点的距离小于 0.4 ,系统就会判定该方向键动作已经释放。

  • Center Region (中心区域)指定了从中心点算起、能够触发中心动作的距离范围。不过要注意,这个功能目前只支持触控板(trackpads)。

  • Wedge Angle (扇区角度)用于指定每个扇区的角度大小。如果设置为 90 degrees 或更低,意味着‘上、下、左、右’四个方向各自拥有独立的扇区,且它们之间互不重叠(同一时间只有一个方向会被判定为按下状态)。如果设置的角度超过 90 degrees ,就意味着这些扇区会发生重叠,从而允许同时有多个动作处于按下状态。

  • Is Sticky (粘滞模式):启用后,即使摇杆或触控板已经离开了当前动作对应的扇区,该动作也会一直保持‘按下’状态,直到摇杆或触控板移动到了另一个扇区为止。

  • On Haptic (按下震动)允许我们定义一种触觉反馈输出,当某个动作被按下时,它会自动触发。

  • Off Haptic (释放震动)允许我们定义一种触觉反馈输出,当某个动作被释放(也就是松手)时,它会自动触发。

针对单个按键绑定的修饰器设置

应用到单个绑定上的绑定修饰器(binding modifiers),可以通过输入项旁边、动作所附带的那个‘绑定修饰器按钮’来访问。

../../_images/openxr_action_binding_modifier.webp

你只需要点击‘添加绑定修饰器’( Add binding modifier )按钮,就可以添加一个新的修饰器啦。

警告

由于 Godot 无法预知每个运行环境(runtime)中的哪些输入支持修饰器,因此在添加修饰器时系统不会做任何限制。如果某个运行环境不支持该修饰器扩展,修饰器会在程序运行时被自动过滤掉。不过要注意,如果把修饰器添加到了错误的输入上,可能会导致运行时报错。

你应该在实际的硬件和运行环境中测试你的动作映射(action map),以确保设置正确无误。

模拟量阈值修饰器

模拟量阈值修饰器(Analog Threshold Modifier)允许你为任何带有布尔输入的模拟量输入(比如扳机键)指定具体的阈值。它主要用来控制输入信号在什么时候被判定为‘已按下’状态。

如果想要使用这个修饰器,你必须先在项目设置里启用‘模拟量阈值扩展(analog threshold extension)’功能。

../../_images/openxr_project_settings_analog_threshold_modifier.webp

模拟量阈值修饰器(analog threshold modifier)包含以下设置:

../../_images/openxr_analog_threshold_modifier.webp

这些(参数/功能)的定义如下:

  • On Threshold (按下阈值)用于指定一个能让动作生效(启用)的阈值。举个例子,如果把值设为 0.6 ,那就意味着当模拟量(analog value)的数值超过 0.6 时,这个动作就会被判定为‘已按下’状态。

  • Off Threshold (释放阈值)用于指定一个能让动作失效(禁用)的阈值。举个例子,如果把值设为 0.4 ,那就意味着当模拟量(analog value)的数值降到 0.4 以下时,这个动作就会被判定为‘已释放’状态。

  • On Haptic (按下震动)允许我们定义一种触觉反馈输出,当输入被按下(触发)时,它就会自动激活。

  • Off Haptic (释放震动)允许我们定义一种触觉反馈输出,当输入被释放(松开)时,它就会自动触发。

修饰器上的触觉反馈

修饰器可以支持自动的触觉反馈输出,当(某些数值)达到设定的阈值时,就会自动触发。

备注

目前,现有的两种修饰器(modifiers)都支持这项功能,但这并不意味着未来推出的修饰器也一定具备这种能力。此外,当前只支持一种类型的触觉反馈,不过未来可能会推出其他选项。

触觉反馈

触觉震动功能允许我们设定一个简单的触觉脉冲(震动反馈):

../../_images/openxr_haptic_vibration.webp

它包含以下选项:

  • Duration (持续时间)指的是脉冲震动的时长,单位是纳秒。如果将其设为 -1 ,就会让运行时(runtime)根据当前的硬件设备,自动选择一个最适合用来触发短促震动的最佳时长。

  • Frequency (频率)指的是脉冲震动的频率,单位是赫兹(Hz)。如果将其设为 0 ,就会让运行时(runtime)根据当前的硬件设备,自动选择一个最合适的频率来触发一次短促的震动。

  • Amplitude 是指脉冲的幅度。