MRTK2.5,指针(Pointer)

MRTK2.5,指针(Pointer)

本文介绍了与Pointer Architecture相比,如何在实践中配置和响应Pointer输入

当检测到新控制器时,将在运行时自动实例化指针。一个控制器可以连接多个指针。例如,使用默认的指针配置文件,Windows Mixed Reality控制器分别获得一条线和一个抛物线形的指针,分别用于常规选择和传送。

指针配置

指针通过MRTK配置为MRTK中输入系统的一部分 MixedRealityPointerProfile 。这种类型的配置文件MixedRealityInputSystemProfile 在MRTK配置检查器中分配给。指针配置文件确定游标,运行时可用的指针类型,以及这些指针如何相互通信以确定哪个指针处于活动状态。

  • 指向范围-定义指针可以与 GameObject 交互的最大距离。
  • 指向光线广播图层蒙版-这是 LayerMask 的优先排列,用于确定任何给定 Pointer 可以与哪些可能的 GameObject进行交互以及尝试进行交互的顺序。这对于确保指针先与其他场景对象先与 UI 元素交互可能很有用。 

指针选项配置

默认的 MRTK 指针配置文件配置包括以下指针类和现成的关联预制件。在运行时可用于系统的指针列表是在“指针”配置文件中的“指针选项”下定义的。开发人员可以利用此列表重新配置现有的指针,添加新的指针或删除其中一个指针。

MRTK2.5,指针(Pointer)

每个Pointer条目由以下数据集定义:

  • 控制器类型-指针 对其有效的一组控制器。
    • 例如,PokePointer 负责用手指“戳”对象,并且默认情况下标记为仅支持铰接式手控制器类型。仅当控制器可用时才实例化指针,尤其是“控制器类型”定义了可以使用此指针预制件创建哪些控制器。
  • 惯用性-允许仅针对特定手(左/右)实例化指针

[!NOTE]将Pointer项的Handedness属性设置为None将有效地将其从系统中禁用,这是从列表中删除该Pointer的替代方法。

  • 指针预制-当与指定控制器类型和惯用性相匹配的控制器开始时,将实例化此预制资产。

可能有多个与控制器关联的指针。例如,在DefaultHoloLens2InputSystemProfile(资产/ MRTK / SDK /配置文件/ HoloLens2 /)中,铰接式手动控制器与PokePointerGrabPointerDefaultControllerPointer(即手动射线)关联。

[!NOTE] MRTK在Assets / MRTK / SDK / Features / UX / Prefabs / Pointers中提供了一组指针预制件。只要它包含Assets / MRTK / SDK / Features / UX / Scripts / Pointers中的指针脚本之一或任何其他实现的脚本,就可以构建一个新的定制预制件IMixedRealityPointer

默认指针类

下列类是可用的即用型MRTK指针,它们在上面概述的默认MRTK指针配置文件中定义。在Assets / MRTK / SDK / Features / UX / Prefabs / Pointers下提供的每个指针预制件均包含一个指针组件。

MRTK2.5,指针(Pointer)

远指针

LinePointer

LinePointer是基本的指针类,它从输入源(即控制器)沿指针方向绘制一条线,并支持沿该方向投射的单个光线。通常,ShellHandRayPointer实例化和利用子类(例如和和传送指针)(它们还会画线以指示传送在何处结束),而不是主要提供通用功能的此类。

对于Oculus,Vive和Windows Mixed Reality等运动控制器,其旋转将与控制器的旋转匹配。对于HoloLens 2铰接式手之类的其他控制器,其旋转与系统提供的手的指向姿势相匹配。

MRTK2.5,指针(Pointer)
CurvePointer

CurvePointer通过允许沿曲线进行多步射线投射扩展LinePointer类。此基本指针类对于弯曲的实例(例如,直线移动的指针始终弯曲成抛物线的瞬态指针)很有用。

ShellHandRayPointer

从扩展的ShellHandRayPointer的实现LinePointer用作MRTK指针配置文件的默认值。该DefaultControllerPointer预制实现ShellHandRayPointer类。

GGVPointer

GGVPointer也称为“凝视/手势/语音”(GGV)指针,主要通过“凝视”和“ Air Tap”或“凝视和语音选择”交互为HoloLens 1样式外观和敲击交互提供动力。GGV指针的位置和方向由头部的位置和旋转驱动。

TouchPointer

TouchPointer负责与统一触摸输入(即触摸屏)的工作。这些是“远距离交互”,因为触摸屏幕的动作会将射线从相机投射到场景中可能较远的位置。

MousePointer

的MousePointer权力的屏幕世界光线投射远远相互作用,但是对于鼠标来代替触摸。

MRTK2.5,指针(Pointer)

[!NOTE]默认情况下,MRTK中不提供鼠标支持,但可以通过向MRTK输入配置文件中添加新的类型的输入数据提供者MouseDeviceManager并将其分配MixedRealityMouseInputProfile给数据提供者来启用鼠标支持。

近指针

PokePointer

PokePointer用于与游戏对象的支持互动“近互动动心了。” 有附带NearInteractionTouchable脚本的GameObject 。对于UnityUI,此指针将查找NearInteractionTouchableUnityUI。PokePointer使用SphereCast确定最接近的可触摸元素,并用于为可按下按钮等提供动力。

使用NearInteractionTouchable组件配置GameObject时,请确保将localForward参数配置为指向按钮或应使其可触摸的其他对象的前端。还要确保可触摸对象的边界与可触摸对象的边界匹配。

有用的戳指针属性:

  • TouchableDistance:可触摸表面可以与之交互的最大距离
  • 视觉效果:用于渲染指尖视觉效果的游戏对象(默认情况下,指环为手指)。
  • 线:从指尖到活动输入表面绘制的可选线。
  • 戳图层蒙版-优先排列的LayerMask数组,用于确定指针可以与哪些GameObjects进行交互以及尝试进行交互的顺序。请注意,GameObject还必须具有NearInteractionTouchable组件才能与戳指针交互。
MRTK2.5,指针(Pointer)
SpherePointer

所述SpherePointer使用UnityEngine.Physics.OverlapSphere以便识别最接近的NearInteractionGrabbable用于交互目的,这对于像“grabbable”输入有用ManipulationHandler。与PokePointer/NearInteractionTouchable功能对相似,为了与Sphere Pointer交互,游戏对象必须包含一个NearInteractionGrabbable脚本组件。

MRTK2.5,指针(Pointer)

有用的球形指针属性:

  • 球体半径:用于查询可抓取对象的球体的半径。
  • Near Object Margin(接近对象边距):在Sphere Cast Radius上方的距离,用于查询检测对象是否在指针附近。“近物体”的总检测半径为“球体投射半径” +“近物体边界”
  • Near Object Sector Angle:用于查询附近物体的指针围绕前轴的角度。使IsNearObject查询功能像一个圆锥体。默认情况下,此设置为66度以匹配Hololens 2行为
MRTK2.5,指针(Pointer)
  • 接近物体的平滑系数:用于接近物体检测的平滑系数。如果在“近物体半径”中检测到物体,则查询的半径将变为“近物体半径” *(1 +“近物体平滑因子”),以降低灵敏度,并使物体更难离开检测范围。
  • 抓取图层蒙版-优先排列的LayerMask数组,用于确定指针可以与哪些GameObjects进行交互以及尝试进行交互的顺序。请注意,NearInteractionGrabbableGameObject还必须具有与SpherePointer进行交互的。[!注意]在MRTK提供的默认GrabPointer预制中,空间感知层已禁用。这样做是为了减少使用空间网格进行球面重叠查询的性能影响。您可以通过修改GrabPointer预制件来启用它。
  • 忽略不在FOV中的碰撞器-是否忽略可能在指针附近但实际上不在视觉FOV中的碰撞器。这样可以防止意外抓握,并且当您可能靠近可抓握但看不到它时,将允许打开手光线。出于性能方面的考虑,Visual FOV是通过圆锥体而不是典型的平截头体定义的。此圆锥体的中心和方向与摄影机的视锥相同,其半径等于显示高度的一半(或垂直FOV)。
MRTK2.5,指针(Pointer)

传送指针

  • TeleportPointer 当采取行动(例如,按下传送按钮)以移动用户时,它将发出传送请求。
  • ParabolicTeleportPointer 当进行抛物线射线投射的动作(即,按下传送按钮)时,将发出传送请求,以移动用户。
MRTK2.5,指针(Pointer)

对混合现实平台的指针支持

下表详细介绍了MRTK中常见平台常用的指针类型。注意:可以向这些平台添加不同的指针类型。例如,您可以向VR添加Poke指针或Sphere指针。此外,带有游戏手柄的VR设备可以使用GGV指针。

OpenVRWindows MRHoloLens 1HoloLens 2
ShellHandRayPointer有效有效有效
传送指针有效有效
GGV指针有效
SpherePointer有效
指针指针有效

通过代码进行指针交互

指针事件接口

实现以下一个或多个接口并以分配给GameObject的MonoBehavioursCollider将接收由相关接口定义的指针交互事件。

事件描述处理程序
焦点改变/焦点改变之前在失去焦点的游戏对象和每次指针改变焦点的对象都获得焦点时引发。IMixedRealityFocusChangedHandler
焦点进入/退出在第一个指针进入游戏对象时获得焦点而在最后一个指针离开时失去焦点。IMixedRealityFocusHandler
指针向下/拖动/向上/单击引发报告指针的按下,拖动和释放。IMixedRealityPointerHandler
触摸开始/更新/完成由触觉良好的指针提出,例如PokePointer报告触摸活动。IMixedRealityTouchHandler

[!NOTE] IMixedRealityFocusChangedHandlerIMixedRealityFocusHandler应在它们引发的对象中进行处理。可以全局接收焦点事件,但是与其他输入事件不同,全局事件处理程序不会基于焦点阻止接收事件(该事件将由全局处理程序和焦点中的相应对象接收)。

指针输入事件在起作用

指针输入事件由MRTK输入系统识别和处理,与常规输入事件类似。区别在于指针输入事件仅由焦点对准的GameObject由触发输入事件的指针以及任何全局输入处理程序处理。常规输入事件由GameObjects集中处理所有活动指针。

  1. MRTK输入系统识别出输入事件已发生
  2. MRTK输入系统将输入事件的相关接口功能触发到所有已注册的全局输入处理程序
  3. 输入系统确定触发事件的指针所针对的GameObject
    1. 输入系统利用Unity的事件系统为聚焦的GameObject上的所有匹配组件触发相关的界面功能
    2. 如果在任何时候输入事件都被标记为use,则该过程将结束,并且不再有GameObjects接收回调。
      • 示例:IMixedRealityFocusHandler将搜索实现该接口的组件以获取GameObject,以获取或失去焦点
      • 注意:如果在当前GameObject上找不到与所需接口匹配的组件,则Unity Event System将冒泡搜索父GameObject。
  4. 如果未注册任何全局输入处理程序,并且找不到具有匹配组件/接口的GameObject,则输入系统将调用每个后备注册的输入处理程序

下面是一个示例脚本,当指针获得或离开焦点时或当指针选择对象时,该脚本将更改附加渲染器的颜色。

public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
    private Color color_IdleState = Color.cyan;
    private Color color_OnHover = Color.white;
    private Color color_OnSelect = Color.blue;
    private Material material;

    private void Awake()
    {
        material = GetComponent<Renderer>().material;
    }

    void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
    {
        material.color = color_OnHover;
    }

    void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
    {
        material.color = color_IdleState;
    }

    void IMixedRealityPointerHandler.OnPointerDown(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerDragged(
         MixedRealityPointerEventData eventData) { }

    void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        material.color = color_OnSelect;
    }
}

查询指针

通过遍历可用的输入源(即可用的控制器和输入)以发现哪些指针附加到它们,可以收集当前活动的所有指针。

var pointers = new HashSet<IMixedRealityPointer>();

// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
    foreach (var pointer in inputSource.Pointers)
    {
        if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
        {
            pointers.Add(pointer);
        }
    }
}

主指针

开发人员可以订阅FocusProviders PrimaryPointerChanged事件,以使焦点中的主指针发生更改时得到通知。这对于识别用户当前是否正在通过注视或手射线或其他输入源与场景进行交互非常有用。

private void OnEnable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}

private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
    ...
}

private void OnDisable()
{
    var focusProvider = CoreServices.InputSystem?.FocusProvider;
    focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);

    // This flushes out the current primary pointer
    OnPrimaryPointerChanged(null, null);
}

PrimaryPointerExample(资产/ MRTK /例子/演示/输入/场景/ PrimaryPointer)现场展示了如何使用PrimaryPointerChangedHandler事件,以响应新的主指针。

MRTK2.5,指针(Pointer)

指针结果

指针Result属性包含用于确定具有焦点的对象的场景查询的当前结果。对于光线投射指针,如默认为运动控制器创建的指针,凝视输入和手部光线,它将包含光线投射命中的位置和法线。

private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
    var result = eventData.Pointer.Result;
    var spawnPosition = result.Details.Point;
    var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
    Instantiate(MyPrefab, spawnPosition, spawnRotation);
}




PointerResultExample场景(资产/ MRTK /实施例/演示/输入/场景/ PointerResult / PointerResultExample.unity)显示了如何使用指针Result在命中位置产卵的对象。

MRTK2.5,指针(Pointer)

禁用指针

要旋转启用和禁用指针(例如,禁用手射线),请通过设置PointerBehavior给定指针类型PointerUtils

// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);

// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
    PointerUtils.SetHandPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetHandGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
    PointerUtils.SetGazePointerBehavior(PointerBehavior.Default);
}

请参阅PointerUtilsTurnPointersOnOff有关更多示例。

通过编辑器进行指针交互

对于由处理的指针事件IMixedRealityPointerHandler,MRTK以PointerHandler组件的形式提供了更多的便利,它允许直接通过Unity Events处理指针事件。

MRTK2.5,指针(Pointer)

指针范围

远指针的设置限制了它们将进行光线投射并与场景中的其他对象进行交互的距离。默认情况下,此值设置为10米。选择该值是为了与HoloLens Shell的行为保持一致。

可以通过更新DefaultControllerPointer预制 ShellHandRayPointer组件的字段来更改此设置:

指针范围-控制指针将与之交互的最大距离。

默认指针范围默认值:当指针不与任何东西交互时,它控制将渲染的指针光线/线条的长度。

也可以看看

原创文章,作者:游戏开发极客,如若转载,请注明出处:https://hololens2.cn/2020/11/07/mrtk2-5%ef%bc%8c%e6%8c%87%e9%92%88%ef%bc%88pointer%ef%bc%89/

发表评论

电子邮件地址不会被公开。 必填项已用*标注