输入事件 - MRTK2

下面的列表概述了要由自定义 MonoBehaviour 组件实现的所有可用输入事件接口。 这些接口将由 MRTK 输入系统调用,以处理基于用户输入交互的自定义应用逻辑。 指针输入事件的处理方式与下面的标准输入事件类型略有不同。

重要

默认情况下,仅当脚本是通过指针而获得焦点的 GameObject 或者是处于焦点的 GameObject 的父级时,脚本才会接收输入事件。

Handler 事件 说明
IMixedRealitySourceStateHandler 检测到源/源丢失 检测到输入源或输入源丢失时引发,例如检测到铰链式手部或者丢失对其的跟踪。
IMixedRealitySourcePoseHandler 源姿势已更改 在源姿势更改时引发。 源姿势表示输入源的常规姿势。 可以通过 IMixedRealityInputHandler<MixedRealityPose> 获取特定姿势,例如六自由度控制器中的抓握姿势或指针姿势。
IMixedRealityInputHandler 输入向下/向上 对二进制输入(如按钮)的更改时引发。
IMixedRealityInputHandler<T> 输入已更改 对给定类型的输入更改时引发。 T 可能有下列值:
- 浮点(例如,返回模拟扳机键)
- Vector2(例如,返回游戏手柄摇杆方向)
- Vector3(例如,返回跟踪设备的位置)
- Quaternion(例如返回被跟踪设备的朝向)
- MixedRealityPose(例如返回完全跟踪的设备)
IMixedRealitySpeechHandler 已识别语音关键字 在识别语音命令配置文件中配置的关键字之一时引发。
IMixedRealityDictationHandler 听写
假设
结果
完成
错误
由听写系统引发以报告听写会话的结果。
IMixedRealityGestureHandler 引发手势事件的时间:
Started
已更新
已完成
已取消
在手势检测时引发。
IMixedRealityGestureHandler<T> 手势已更新/已完成 在检测到包含给定类型的附加数据的手势时引发。 有关 T 的可能值的详细信息,请参阅手势事件
IMixedRealityHandJointHandler 手部关节已更新 在更新手部关节时由铰链式手部控制器引发。
IMixedRealityHandMeshHandler 手部网格已更新 更新手部网格时由铰接式手部控制器引发。
IMixedRealityInputActionHandler 操作已开始/已结束 引发以指示映射到动作的输入的动作开始和结束。

正在生效的输入事件

在脚本级别,可以通过实现上表中显示的事件处理程序接口之一来使用输入事件。 通过用户交互触发输入事件时,将发生以下情况:

  1. MRTK 输入系统识别出输入事件已经发生。
  2. MRTK 输入系统对所有已注册的全局输入处理程序触发输入事件的相关接口函数
  3. 对于向输入系统注册的每个活动指针:
    1. 输入系统确定哪个 GameObject 已由当前指针聚焦。
    2. 输入系统利用 Unity 的事件系统对聚焦的 GameObject 上的所有匹配组件触发相关接口函数。
    3. 如果在任意时间某个输入事件标记为已使用,则该过程将会结束,并且不再有 GameObject 接收回调。
      • 示例:当识别出语音命令时,将搜索实现 IMixedRealitySpeechHandler 接口的组件。
      • 注意:如果在当前 GameObject 中找不到与所需接口匹配的组件,Unity 事件系统将努力搜索父 GameObject。
  4. 如果未注册全局输入处理程序并且未找到具有匹配组件/接口的 GameObject,则输入系统将调用每个已注册的回退输入处理程序

注意

与上面列出的输入事件接口相比,指针输入事件的处理方式略有不同。 具体来说,指针输入事件仅由触发输入事件的指针聚焦的 GameObject 以及任何全局输入处理程序处理。 普通输入事件由所有活动指针聚焦的 GameObject 处理。

输入事件接口示例

下面的代码演示如何使用 IMixedRealitySpeechHandler 接口。 如果用户在关注具有 ShowHideSpeechHandler 类的 GameObject 时说出“缩小”或“放大”这两个词时,GameObject 会将自身缩小一半或放大为原来的两倍。

public class ShowHideSpeechHandler : MonoBehaviour, IMixedRealitySpeechHandler
{
    ...

    void IMixedRealitySpeechHandler.OnSpeechKeywordRecognized(SpeechEventData eventData)
    {
        if (eventData.Command.Keyword == "smaller")
        {
            transform.localScale *= 0.5f;
        }
        else if (eventData.Command.Keyword == "bigger")
        {
            transform.localScale *= 2.0f;
        }
    }
}

注意

IMixedRealitySpeechHandler 输入事件要求所需要的关键字已经在 MRTK 语音命令配置文件中预先注册。

注册全局输入事件

若要创建侦听全局输入事件的组件,而忽略可能处于焦点的 GameObject,组件必须将自身注册到输入系统。 注册后,此 MonoBehaviour 的任何实例都将接收输入事件以及当前处于焦点的任何 GameObject 和其他全局注册侦听器。

如果输入事件已标记为“已使用”,则全局注册的处理程序仍将全部接收回调。 但是,处于焦点的所有 GameObject 都不会收到事件。

全局输入注册示例

public class GlobalHandListenerExample : MonoBehaviour,
    IMixedRealitySourceStateHandler, // Handle source detected and lost
    IMixedRealityHandJointHandler // handle joint position updates for hands
{
    private void OnEnable()
    {
        // Instruct Input System that we would like to receive all input events of type
        // IMixedRealitySourceStateHandler and IMixedRealityHandJointHandler
        CoreServices.InputSystem?.RegisterHandler<IMixedRealitySourceStateHandler>(this);
        CoreServices.InputSystem?.RegisterHandler<IMixedRealityHandJointHandler>(this);
    }

    private void OnDisable()
    {
        // This component is being destroyed
        // Instruct the Input System to disregard us for input event handling
        CoreServices.InputSystem?.UnregisterHandler<IMixedRealitySourceStateHandler>(this);
        CoreServices.InputSystem?.UnregisterHandler<IMixedRealityHandJointHandler>(this);
    }

    // IMixedRealitySourceStateHandler interface
    public void OnSourceDetected(SourceStateEventData eventData)
    {
        var hand = eventData.Controller as IMixedRealityHand;

        // Only react to articulated hand input sources
        if (hand != null)
        {
            Debug.Log("Source detected: " + hand.ControllerHandedness);
        }
    }

    public void OnSourceLost(SourceStateEventData eventData)
    {
        var hand = eventData.Controller as IMixedRealityHand;

        // Only react to articulated hand input sources
        if (hand != null)
        {
            Debug.Log("Source lost: " + hand.ControllerHandedness);
        }
    }

    public void OnHandJointsUpdated(
                InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData)
    {
        MixedRealityPose palmPose;
        if (eventData.InputData.TryGetValue(TrackedHandJoint.Palm, out palmPose))
        {
            Debug.Log("Hand Joint Palm Updated: " + palmPose.Position);
        }
    }
}

注册备用输入事件

备用输入处理程序类似于注册的全局输入处理程序,但被视为输入事件处理的最后手段。 只有没有找到全局输入处理程序并且没有 GameObject 处于焦点时,才会利用备用输入处理程序。

备用输入处理程序示例

public class GlobalHandListenerExample : MonoBehaviour,
    IMixedRealitySourceStateHandler // Handle source detected and lost
{
    private void OnEnable()
    {
        CoreServices.InputSystem?.PushFallbackInputHandler(this);
    }

    private void OnDisable()
    {
        CoreServices.InputSystem?.PopFallbackInputHandler();
    }

    // IMixedRealitySourceStateHandler interface
    public void OnSourceDetected(SourceStateEventData eventData)
    {
        ...
    }

    public void OnSourceLost(SourceStateEventData eventData)
    {
        ...
    }
}

如何停止输入事件

每个输入事件接口提供一个 BaseInputEventData 数据对象作为接口上每个函数的参数。 这个事件数据对象是从 Unity 自己的 AbstractEventData 扩展而来。

要阻止输入事件通过其执行而进行传播(如上文所述),组件可以调用 AbstractEventData.Use() 以将事件标记为已使用。 这将阻止任何其他 GameObject 接收当前输入事件,但全局输入处理程序除外。

注意

调用 Use() 方法的组件将阻止其他 GameObject 接收该输入事件。 但是,当前 GameObject 上的其他组件仍将接收输入事件并触发任何相关的接口函数。

请参阅