控制器,指针和焦点
控制器,指针和焦点(Controllers, pointers, and focus)是更高级的概念,它们建立在核心输入系统所建立的基础之上。它们一起提供了场景中与对象交互的大部分机制。
Controllers (控制器)
控制器表示物理控制器(6个自由度,全关节手等)。它们是由设备管理器创建的,负责与相应的底层系统进行通信,并将该数据转换为MRTK形数据和事件。
例如,在Windows Mixed Reality平台上,WindowsMixedRealityArticulatedHand
是一个控制器,负责与底层Windows手部追踪API交互,获取有关手的关节,姿势和其他属性的信息。它负责将这些数据转换为相关的MRTK事件(例如,通过调用RaisePoseInputChanged或RaiseHandJointsUpdated)并更新其内部状态,以便对TryGetJointPose
的查询将返回正确的数据。
通常,控制器的生命周期将涉及:
- 在检测到新来源(例如,检测并开始跟踪一只手)时,设备管理器就会创建一个控制器。
- 在控制器的Update()循环中,它调用其底层API系统。
- 在同一更新循环中,它通过直接调用核心输入系统本身来引发输入事件更改(例如,引发HandMeshUpdated或HandJointsUpdated)。
Pointers and focus (指针和焦点)
指针用于与游戏对象进行交互。本节介绍如何创建指针,如何更新指针以及如何确定被聚焦的对象。它还将介绍存在的不同类型的指针以及它们处于活动状态的场景。
指针类别
指针通常属于以下类别之一:
Far pointers(远指针)
这些类型的指针用于与距离用户较远的对象进行交互(“远距离”仅定义为“不靠近”)。这些类型的指针通常会投射出可以深入世界的线,并允许用户与不紧邻它们的对象进行交互并对其进行操作。
Near pointers(近指针)
这些类型的指针用于与距离用户足够近的对象进行交互以进行抓取,触摸和操纵。通常,这些类型的指针通过查找附近的对象来与对象进行交互。(通过在较小范围内进行射线投射,进行球面投射来查找附近的对象,或者枚举被认为是可抓取/可触摸的对象列表)。
Teleport pointers(传送指针)
这些类型的指针插入到传送系统(teleportation system)中,以处理将用户移动到指针指向的位置。
Pointer mediation(指针调解器)
因为单个控制器可以具有多个指针(例如,全关节手可以具有近距交互指针和远距交互指针),所以存在一个组件,负责调解哪个指针应处于活动状态。
例如,当用户的手接近可按下的按钮时,ShellHandRayPointer
应该停止显示,并且PokePointer
应该被启用。
这是由DefaultPointerMediator
处理的,它负责根据所有指针的状态确定哪些指针处于活动状态。它做的一个关键事情是当一个近指针靠近对象时,禁用远指针 (参见 DefaultPointerMediator
).
可以通过更改指针配置文件上的 PointerMediator
属性来提供指针调解器的替代实现。
如何禁用指针
由于指针调解器每帧运行,所以它最终控制所有指针的活动/非活动状态。因此,如果在代码中设置了指针的IsInteractionEnabled属性,则指针调解器将在每帧覆盖它。相反,您可以指定 PointerBehavior
控制指针是打开还是关闭自己。请注意,这仅在使用MRTK中的 FocusProvider
和 DefaultPointerMediator
默认设置时有效。
示例:在MRTK中禁用手部射线
以下代码将关闭MRTK中的手部射线:
// 关闭所有手部射线
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);
// 仅关闭右手的射线
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);
以下代码将使手部射线返回其在MRTK中的默认行为:
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default);
以下代码将强制打开手射线,无论是否靠近可抓取的物体:
// 打开所有手部射线
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOn);
查看 PointerUtils
和 TurnPointersOnOff
有关更多示例。
FocusProvider
FocusProvider
是负责遍历所有指针列表并弄清楚每个指针的焦点对象是什么的主力部分。
在每个Update()
调用中,这将:
通过射线投射并执行指针本身配置的命中检测来更新所有指针(例如,球体指针可以指定SphereOverlap raycastMode,因此FocusProvider将进行基于球体的碰撞)
在每个指针的基础上更新聚焦对象(即,如果一个对象获得焦点,它也会触发那些对象的事件,如果一个对象失去焦点,它将触发焦点丢失,等等)。
指针配置和生命周期
指针可以配置 在输入系统配置文件的Pointers部分中。
The lifetime of a pointer is generally the following:
设备管理器将检测到控制器的存在。然后,该设备管理器将通过调用
RequestPointers
来创建与控制器关联的一组指针.FocusProvider在其Update()循环中,将遍历所有有效指针并执行关联的射线或命中检测逻辑。所以也有可能同时有多个焦点对象。
- 因为有可能同时有多个输入源处于活动状态(例如,两只手处于激活状态),所以也可以有多个对象同时聚焦。
当发现控制器源丢失时,设备管理器将销毁与丢失的控制器关联的指针。