mrtk_developmentreleases/2.0.0releases/2.1.0releases/2.2.0
  • 指南
  • API 文档
  • 指南
  • 功能概述
  • 输入系统 Input System
  • 指针 Pointers

    Show / Hide Table of Contents
    • MRTK入门
      • 发布说明
      • MRTK包内容
      • 从早期版本更新
      • 从HTK更新
      • 生成和部署MRTK
      • NuGet包
      • MRTK配置对话框
      • 开始使用 MRTK和XR SDK
      • 性能
      • 全息图稳定
      • 在大型项目中使用MRTK
    • 架构
      • 概述
      • 框架和运行时
      • 输入系统
        • 术语
        • 核心系统
        • Controllers, pointers, and focus
      • 系统,扩展服务和 data providers
    • 功能概述
      • 边界系统 Boundary System
        • 边界系统概述
        • 配置边界可视化
      • 相机系统 Camera System
        • 相机系统概述
        • Camera Settings Providers
          • Windows 混合现实相机设置
          • Unity AR相机设置[实验性]
          • 创建camera settings provider
      • 跨平台支持
        • 为iOS和Android配置MRTK
      • 检测平台能力
      • 诊断系统 Diagnostics System
        • 诊断系统概述
        • 配置诊断系统
        • 使用可视化分析器
      • 扩展服务 Extension Services
        • 扩展服务创建向导
        • 场景过渡服务概述
      • 输入系统 Input System
        • 输入概览
        • 输入动作 Input Actions
        • 输入事件 Input Events
        • Input Providers
          • Input Providers 概述
          • 创建一个 input data provider
        • 控制器 Controllers
        • 眼动跟踪 Eyes
          • 概述
          • 入门
          • 通过代码访问数据
          • 验证跟踪校准 Validate Tracking Calibration
        • 凝视 Gaze
        • 手势 Gestures
        • 手部 Hands
        • 如何添加近距离交互 Near Interaction
        • 编辑器内输入模拟 In-Editor Input Simulation
        • 指针 Pointers
        • 语音输入 Voice Input
          • 语音转录 Dictation
          • 语音(命令和控制) Speech
      • 多场景系统 Multi Scene System
        • 多场景系统概述
        • 场景类型 Scene Types
        • 内容场景加载 Content Scene Loading
        • 监测内容加载 Monitoring Content Loading
        • 光照场景操作 Lighting Scene Operations
      • 打包 Packaging
        • MRTK包 MRTK Packages
        • MRTK模块化 MRTK Modularization
      • 配置文件 Profiles
        • 配置文件概述
        • 配置指南 Configuration Guide
      • 渲染 Rendering
        • 材质实例概述 Material Instance Overview
        • Shaders
          • MRTK标准着色器 MRTK Standard Shader
      • 服务 Services
        • 什么是混合现实特性
        • 什么是 MixedRealityServiceRegistry 和IMixedRealityServiceRegistrar
        • 扩展服务 Extension services
      • 空间感知系统 Spatial Awareness System
        • 空间感知概述
        • Spatial Observers
          • 为设备配置 Observers
          • 为Editor配置 Observers
          • 通过代码控制 Observers
          • 创建自定义 Observer
      • 传送系统概述 Teleport System Overview
      • 工具
        • Dependency Window
        • Extension Service Creation Wizard
        • Holographic Remoting
        • Input Animation Recording
          • Input Animation File Format Specification
        • Optimize Window
        • Runtime tools
          • Controller Mapping tool
      • UX 构建模块
        • 工具箱窗口 Toolbox Window
        • 按钮 Button
        • 边界框 Bounding Box
        • 对象操纵器 Object Manipulator
        • Manipulation Handler [废弃]
        • Slate
        • 系统键盘 System Keyboard
        • 可交互的 Interactable
        • Solvers
          • 点击放置 Tap to Place
        • 对象集合 Object Collection
        • 提示工具条 Tooltips
        • 滑动条 Slider
        • 手部菜单 Hand Menu
        • 近处菜单 Near Menu
        • 应用程序栏 App Bar
        • 指尖可视化 Fingertip Visualization
        • 进度指示器 Progress Indicator
        • 对话框 Dialog [实验性]
        • 手势教学 Hand Coach [实验性]
        • 可滚动对象集合 Scrolling Object Collection [实验性]
        • 脉冲着色器 Pulse Shader [实验性]
        • 停靠控件 Dock Control [实验性]
        • HoloLens键盘助手 [实验性]
      • 示例场景
        • 示例中心
        • 手势交互示例场景
        • 眼动跟踪示例场景
    • Contributing
      • Contributing Overview
      • Coding Guidelines
      • Writing and Running Tests
      • Writing Documentation
      • Pull Requests
      • Experimental Features
      • Breaking Changes
      • How to use DocFX
    • Planning
      • Roadmap
    • Notice
    • Authors

    Pointers (指针)

    Pointer

    This article discusses how to configure and respond to Pointer input in practice, compared to Pointer Architecture

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

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

    Pointer 配置

    Pointers通过MixedRealityPointerProfile 配置为MRTK中的输入系统的一部分。此类profile在 MRTK Configuration inspector中分配给MixedRealityInputSystemProfile 。pointer profile确定光标,运行时可用的Pointers类型以及这些pointers如何相互通信来确定哪个pointer处于活动状态。

    • Pointing Extent - 定义pointer可以与GameObject交互的最大距离。

    • Pointing Raycast Layer Masks - 这是LayerMasks的优先数组,用于确定任何给定Pointer可以交互的GameObjects以及尝试交互的顺序。这对于确保pointer最先与场景对象中UI元素交互可能很有用。 Pointer Profile Example

    Pointer 选项配置

    默认的MRTK Pointer Profile配置包括以下pointer类和现成的关联预制体。在运行时可用于系统的pointer列表在Pointer profile的Pointer Options下定义。开发人员可以利用此列表重新配置现有的Pointers,添加新的Pointers或删除其中一个。

    Pointer Options Profile Example

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

    • Controller Type - pointer对其有效的一组控制器

      • 例如,PokePointer 负责用手指“戳”对象,并且默认情况下标记为仅支持全关节手控制器类型。仅当控制器可用时才实例化Pointers,特别是Controller Type 定义了可以使用此pointer预制体可以与哪些控制器进行创建。
    • Handedness - 允许仅针对特定手(左/右)实例化pointer

    Note

    将Pointer条目的 Handedness 属性设置为None ,可以有效地将其从系统中禁用,这是从列表中删除该Pointer的替代方法。

    • Pointer Prefab - 当控制器匹配指定的控制器类型且handedness开始被追踪时,将实例化此预制体。

    可能有多个pointers与一个控制器关联。例如,在默认 HoloLens 2 profile 中,全连接手控制器与PokePointer, GrabPointer 和DefaultControllerPointer(即手部射线)相关联。

    Note

    MRTK在Assets/MixedRealityToolkit.SDK/Features/UX/Prefabs/Pointers中提供了一组pointer预制体。如果包含Assets/MixedRealityToolkit.SDK/Features/UX/Scripts/Pointers 中的pointer脚本之一或任何其他实现IMixedRealityPointer的脚本,就可以构建新的自定义预制体。

    默认 pointer 类

    下列类是现成可用的 MRTK pointers,这些类已在上面概述的默认 MRTK Pointer Profile 中定义。在Assets/MixedRealityToolkit.SDK/Features/UX/Prefabs/Pointers 下提供的每个pointer预制体都包含这些pointer组件之一。

    MRTK Default Pointers

    Far pointers

    LinePointer

    LinePointer 是基本的pointer类,它从输入源(即控制器)沿pointer方向绘制线条。通常,诸如ShellHandRayPointer的子类和teleport pointers会被实例化并利用(它也画线来指示传送将在哪里结束),而不是这个主要提供公共功能的类。

    对于Oculus,Vive和Windows Mixed Reality等运动控制器,其旋转将与控制器的旋转相匹配。对于如 HoloLens 2全关节手之类的其他控制器,其旋转与系统提供的手部pointing pose 相匹配。

    ShellHandRayPointer

    ShellHandRayPointer 的实现从LinePointer扩展而来,被用作MRTK Pointer Profile 的默认设置。 DefaultControllerPointer 预制体实现了ShellHandRayPointer 类。

    GGVPointer

    GGVPointer也称为Gaze/Gesture/Voice (GGV) pointer,主要通过凝视和Air Tap或注视和语音选择交互来为HoloLens 1型样式和点击交互赋能。GGVpointer的位置和方向由头部的位置和旋转来驱动。

    TouchPointer

    TouchPointer 负责处理Unity Touch输入(即触摸屏)。这些是'far interactions',因为触摸屏幕的动作会将射线从相机投射到场景中可能较远的位置。

    MousePointer

    MousePointer为远距离互动提供了一个屏幕,可以使用世界射线,但适用于鼠标而不是触摸。


    Note

    默认情况下,MRTK中不提供鼠标支持,但可以通过向MRTK输入配置文件添加类型为MouseDeviceManager的新Input Data Provider来启用鼠标支持并将 MixedRealityMouseInputProfile分配给data provider。

    Near pointers

    PokePointer

    PokePointer 用于与支持 “near interaction touchable”的游戏对象进行交互。这些游戏对象具有附加的NearInteractionTouchable脚本。对于UnityUI,此pointer将查找NearInteractionTouchableUnityUI。PokePointer使用SphereCast确定最接近的可触摸元素,并用于为可按下的按钮等事物赋能。

    When configuring the GameObject with the NearInteractionTouchable component, make sure to configure the localForward parameter to point out of the front of the button or other object that should be made touchable. Also make sure that the touchable's bounds matches the bounds of the touchable object.

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

    有用的 Poke Pointer 属性:

    • TouchableDistance: 可触摸表面可以被互动的最大距离
    • Visuals: 用于渲染指尖视觉效果(finger tip visual)的游戏对象(默认情况下,环在手指上)。
    • Line: 从指尖到活动输入表面绘制的可选线。
    • Poke Layer Masks - 优先排列的LayerMask数组,用于确定pointer可以与哪些游戏对象进行交互以及尝试进行交互的顺序。请注意,GameObject还必须具有NearInteractionTouchable 组件才能与 poke pointer进行交互。
    SpherePointer

    *SpherePointer*使用 UnityEngine.Physics.OverlapSphere 进行标识最近的NearInteractionGrabbable对象进行交互,这对于“可抓取的”输入(如ManipulationHandler)很有用。类似于 PokePointer/NearInteractionTouchable 的功能对,如果要与Sphere Pointer交互,游戏对象必须包含NearInteractionGrabbable 脚本组件。

    有用的Sphere Pointer属性:

    • Sphere Cast Radius: 用于查询可抓取对象的球体的半径.
    • Grab Layer Masks - 优先排列的LayerMask数组,用于确定pointer可以与哪些游戏对象进行交互以及尝试进行交互的顺序。注意,GameObject还必须具有一个NearInteractionGrabbable`才能与SpherePointer交互。
    Note

    在MRTK提供的默认GrabPointer预制体中,禁用了Spatial Awareness 层。这样做是为了减少球体与空间网格重叠查询的性能影响。您可以通过修改GrabPointer预制体来启用它。

    Teleport pointers

    • TeleportPointer 将在采取行动(即,按下传送按钮)时引发传送请求,以移动用户。
    • ParabolicTeleportPointer 将在采取行动(即,按下传送按钮)时引发传送请求,用使用抛物线射线来移动用户。

    对混合现实平台的Pointer支持

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

    OpenVR Windows Mixed Reality HoloLens 1 HoloLens 2
    ShellHandRayPointer 有效 有效 有效
    TeleportPointer 有效 有效
    GGVPointer 有效
    SpherePointer 有效
    PokePointer 有效

    通过代码进行的Pointer交互

    Pointer 事件接口

    MonoBehaviours that implement one or more of the following interfaces and are assigned to a GameObject with a Collider will receive Pointer interactions events as defined by the associated interface.

    实现以下一个或多个接口并分配给具有Collider的GameObject的MonoBehaviours 将会接收关联接口定义的pointer交互事件。

    事件 描述 Handler
    Focus 改变前 / Focus 改变 在每次pointer改变焦点(focus)时,同时引起游戏对象失去焦点和另一个对象获得焦点。 IMixedRealityFocusChangedHandler
    Focus Enter / Exit 当第一个pointer进入游戏对象时,该对象获得焦点;当最后一个pointer离开时,该对象失去焦点。 IMixedRealityFocusHandler
    Pointer Down / Dragged / Up / Clicked 报告pointer按下、拖动和释放。 IMixedRealityPointerHandler
    Touch 开始 / 更新 / 完成 由类似PokePointer的 感知触摸 pointers 引发来报告触摸活动 IMixedRealityTouchHandler
    Note

    IMixedRealityFocusChangedHandler 和IMixedRealityFocusHandler 应该在引发它们的对象中进行处理。可以全局接收焦点事件(focus events),但是与其他输入事件不同,全局 event handler 不会基于焦点阻止接收事件(该事件将同时被全局handler和焦点中的相应对象接收)

    Pointer input events in action

    Pointer input events are recognized and handled by the MRTK input system in a similar way as regular input events. The difference being that pointer input events are handled only by the GameObject in focus by the pointer that fired the input event - as well as any global input handlers. Regular input events are handled by GameObjects in focus for all active pointers.

    pointer输入事件由MRTK输入系统以与 常规输入事件相似的方式进行识别和处理。区别在于pointer输入事件仅由触发输入事件的pointer的焦点GameObject以及任何全局input handlers来处理。所有活动指针的常规输入事件由焦点GameObjects 处理。

    1. MRTK输入系统识别出发生输入事件
    2. MRTK输入系统将输入事件的相关接口功能触发到所有已注册的全局input handlers
    3. 输入系统确定触发事件的pointer的焦点GameObject
      1. 输入系统利用Unity's Event System 触发焦点GameObject上所有匹配组件的相关接口功能
      2. 如果在任何时候输入事件已被marked as used, 则该过程将结束,并且不再有GameObjects接收回调。
        • 示例:实现接口IMixedRealityFocusHandler 的组件将在GameObject中获得或失去焦点。
        • 注意:如果在当前GameObject上找不到与所需接口匹配的组件,则Unity事件系统将逐级向上搜索父辈GameObject。
    4. 如果未注册任何全局 input handlers ,并且找不到具有匹配组件/接口的GameObject,则输入系统将调用每个后备注册的 input handlers

    示例

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

    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;
        }
    }
    

    查询 Pointers

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

    var pointers = new HashSet<IMixedRealityPointer>();
    
    // 找到所有有效pointers
    foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
    {
        foreach (var pointer in inputSource.Pointers)
        {
            if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
            {
                pointers.Add(pointer);
            }
        }
    }
    

    Primary Pointer

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

    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);
    
        // 这将清除当前primary pointer
        OnPrimaryPointerChanged(null, null);
    }
    

    The PrimaryPointerExample 场景 显示了如何使用PrimaryPointerChangedHandler 以使事件响应新的primary pointer.

    Pointer Result

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

    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 场景 显示了如何使用pointerResult 以在命中位置生成对象.

    禁用 Pointers

    要启用和禁用pointer(例如,禁用手部射线), 请通过PointerUtils为给定的pointer类型设置PointerBehavior。

    // 禁用手部射线
    PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);
    
    // 仅禁用右手的射线
    PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);
    
    // 禁用gaze pointer
    PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);
    
    // 设置行为以匹配HoloLens 1
    // 注意,如果在HoloLens 2上,则必须配置pointer profile,以使GGVpointer为全关节手显示。
    public void SetHoloLens1()
    {
        PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
        PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
        PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
        PointerUtils.SetGGVBehavior(PointerBehavior.Default);
    }
    

    有关更多示例,请参见 PointerUtils 和TurnPointersOnOff 。

    通过编辑器进行的Pointer交互

    For pointer events handled by IMixedRealityPointerHandler, MRTK provides further convenience in the form of the PointerHandler component which allows pointer events to be handled directly via Unity Events.

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

    Pointer 范围

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

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

    Pointer Extent - 控制pointer将与之交互的最大距离

    Default Pointer Extent - 控制pointer射线/线条的长度 当pointer不与任何东西交互时呈现。

    建议浏览

    • Pointer Architecture
    • Input Events
    • Improve this Doc
    In This Article
    • Pointer 配置
      • Pointer 选项配置
      • 默认 pointer 类
        • Far pointers
        • Near pointers
        • Teleport pointers
    • 对混合现实平台的Pointer支持
    • 通过代码进行的Pointer交互
      • Pointer 事件接口
        • Pointer input events in action
        • 示例
      • 查询 Pointers
        • Primary Pointer
      • Pointer Result
      • 禁用 Pointers
    • 通过编辑器进行的Pointer交互
    • Pointer 范围
    • 建议浏览
    Back to top Generated by DocFX