鸟语天空
XR Interaction Toolkit
post by:追风剑情 2022-7-22 17:37

参考文档

XR Interaction Toolkit Manual
XR Interaction Toolkit Examples
Unity - Manual: XR Input
Unity - Packages: Input System

什么是XR?

扩展现实(Extended Reality,简称XR),是AR(增强现实)、VR(虚拟现实)、MR(混合现实)等多种技术的统称。

111111111111111.png

11111.png

  一个高级的,基于组件的交互系统,用于创建VR和AR体验。它提供了一个框架,以及一个将这两种类型的组件连接在一起的交互管理器。它还包含了您可以用于运动和绘图视觉效果的组件。

XR Origin 组件

11111111111.png

Tracking Origin Mode
 ○ Not Specified:使用输入设备的默认跟踪原点模式。
 ○ Device: 输入设备将相对于第一个已知位置进行跟踪。
 ○ Floor:输入设备将相对于地板上的位置进行跟踪。

XROrigin

抓取交互

  需要在希望被抓取的对象上挂 XRGrabInteractable 脚本。找到 XR Origin/Camera Offset/LeftHand Controller 对象上的 XRRayInteractor 脚本上的 Force Grab 属性,当此属性为true时,对象将被瞬移到手上。当此属性为false时,对象将被固定在手柄射线的端点上。

相互作用事件(Interactor Events)

  XRRayInteractor 脚本上找到 Interactor Events 属性,展开后可以设置相互作用事件回调。手柄进入事件(Hover Entered)、手柄离开事件(Hover Exited)、抓取事件(Select Entered)、释放事件(Select Exited)。

1111.png

触觉事件(Haptic Events)

XRRayInteractor 脚本上找到 Haptic Events 属性,展开后可以为一些事件设置振动参数。

3333.png

手柄交互

  手柄交互由 XR Origin/Camera Offset/LeftHand Controller 上挂的 ActionBasedController 组件控制。ActionBasedController 负责将从XR输入子系统(XR input subsystem)中获取到的特征值转成XR交互状态(XR interaction state),例如 “选中”,以及控制设备(如,手柄)与控制模型之间的姿态同步。

判断Trigger键是否按下

ActionBasedController rightHandController;
//只会在按下那一刻返回true
if (rightHandController.activateAction.action.triggered)
{
	Debug.Log("按下手柄上的Trigger键");
}  

判断Trigger键当前动作阶段(Phase)

ActionBasedController rightHandController;
InputActionPhase phase = rightHandController.activateAction.action.phase;
switch(phase)
{
	case InputActionPhase.Disabled:
		material.SetColor("_Color", Color.red);
		break;
	case InputActionPhase.Waiting://Trigger键未按下
		material.SetColor("_Color", Color.yellow);
		break;
	case InputActionPhase.Started:
		material.SetColor("_Color", Color.green);
		break;
	case InputActionPhase.Performed://Trigger键按下
		material.SetColor("_Color", Color.blue);
		break;
	case InputActionPhase.Canceled:
		material.SetColor("_Color", Color.white);
		break;
} 

当 Trigger 键处于 InputActionPhase.Performed 阶段时 IsPressed() 方法返回 true
bool isTriggerPressed = rightHandController.activateAction.action.IsPressed();

InputAction中监听按下的方法

WasPressedThisFrame()
在触发按下动作帧中返回true

WasPerformedThisFrame()
在保持按下状态帧中返回true

WasReleasedThisFrame()
在触发释放动作帧中返回true

IsPressed()
只要超过按钮按下阈值就返回true

判断Grip键是否按下

ActionBasedController rightHandController;
//只会在按下那一刻返回true
if (rightHandController.selectAction.action.triggered)
{
	Debug.Log("按下手柄上的Grip键");
} 

//如果Grip处于按下状态,会一直返回true
if (rightHandController.selectAction.action.IsPressed())
{
	Debug.Log("按住手柄上的Grip键");
}  

用 triggered 属性判断按下动作,用 IsPressed() 判断是否持续按住不放。
activateAction.action.IsPressed() 与 activateActionValue.action.IsPressed() 没有区别。

按键枚举

namespace UnityEngine.XR.Interaction.Toolkit
{
	public static class InputHelpers
	{
		public enum Button
		{
		     None = 0,
		     MenuButton = 1,//菜单键
		     Trigger = 2,//扳机键
                     Grip = 3,//抓取键
                     TriggerButton = 4,//扳机键
                     TriggerPressed = 4,//扳机键
                     GripButton = 5,//抓取键
                     GripPressed = 5,//抓取键
                     PrimaryButton = 6,//右手A键按下 或 左手X键按下
                     PrimaryTouch = 7,//右手A键触摸 或 左手X键触摸
                     SecondaryButton = 8,//右手B键按下 或 左手Y键按下
                     SecondaryTouch = 9,//右手B键触摸 或 左手Y键触摸
                     Primary2DAxisTouch = 10,//右手摇杆触摸
                     Primary2DAxisClick = 11,//右手摇杆Click
                     Secondary2DAxisTouch = 12,//左手摇杆触摸
                     Secondary2DAxisClick = 13,//左手摇杆Click
                     PrimaryAxis2DUp = 14,//右手摇杆向上
                     PrimaryAxis2DDown = 15,//右手摇杆向下
                     PrimaryAxis2DLeft = 16,//右手摇杆向左
                     PrimaryAxis2DRight = 17,//右手摇杆向右
                     SecondaryAxis2DUp = 18,//左手摇杆向上
                     SecondaryAxis2DDown = 19,//左手摇杆向下
                     SecondaryAxis2DLeft = 20,//左手摇杆向左
                     SecondaryAxis2DRight = 21//左手摇杆向右
		}
	}
}  

注意事项

1. 存在两个InputDevice类,分别是 UnityEngine.XR.InputDeviceUnityEngine.InputSystem.InputDevice; 建议定义两个别名:
using XRInputDevice = UnityEngine.XR.InputDevice;
using ISInputDevice = UnityEngine.InputSystem.InputDevice;

判断扳机键(Trigger)是否按下

//检测右边手柄扳机键是否按下
XRInputDevice rightHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (rightHandDevice.isValid)
{
    bool isRightTriggerDown;
    //如果一直按住,将持续返回true
    rightHandDevice.TryGetFeatureValue(PXR_Usages.triggerTouch, out isRightTriggerDown);
} 

判断扳机键(Trigger)是否按下 (推荐)

UnityEngine.XR.Interaction.Toolkit.InputHelpers 类为 UnityEngine.XR.InputDevice 提供了扩展方法:
public static bool IsPressed(this InputDevice device, Button button, out bool isPressed, float pressThreshold = -1);

//检测右边手柄扳机键是否按下
XRInputDevice rightHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (rightHandDevice.isValid)
{
    bool isPressed;
    //如果一直按住,将持续返回true
    //经测试:Button.Trigger、Button.TriggerButton、Button.TriggerPressed 3种效果等同
    rightHandDevice.IsPressed(InputHelpers.Button.TriggerPressed, out isPressed);
} 

模型监听扳机键(Trigger)是否按下

using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class Test : MonoBehaviour
{
    public ActionBasedController rightHandController;
    public XRSimpleInteractable interactable;

    private void Update()
    {
        //判断手柄射线是否指向模型
        if (interactable.isHovered)
        {
            //判断是否按下Trigger键
            //只会在按下那一刻返回true
            if (rightHandController.activateAction.action.triggered)
            {
                Debug.Log("按下手柄上的Trigger键");
            }
        }
    }
}  
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
using UnityEngine.XR.Interaction.Toolkit;
/// <summary>
/// 挂在模型上,用来监听手柄板机键(Trigger)是否按下
/// </summary>
[RequireComponent(typeof(XRSimpleInteractable))]
public class XRTriggeredEvent : MonoBehaviour
{
    public ActionBasedController leftHandController;
    public ActionBasedController rightHandController;
    public XRSimpleInteractable interactable;

    [Serializable]
    public class OnTriggeredEvent : UnityEvent { }

    [FormerlySerializedAs("triggered")]
    [SerializeField]
    private OnTriggeredEvent m_OnTriggered = new OnTriggeredEvent();

    private void Update()
    {
        if (interactable.isHovered)
        {
            bool leftTriggered = false;
            bool rightTriggered = false;

            if (leftHandController != null)
            {
                leftTriggered = leftHandController.activateAction.action.triggered;
            }

            if (rightHandController != null)
            {
                rightTriggered = rightHandController.activateAction.action.triggered;
            }

            if (leftTriggered || rightTriggered)
            {
                //在模型上按下Trigger键(左手或右手)
                m_OnTriggered?.Invoke();
            }
        }
    }
}  

获取摇杆值

//获取右手摇杆值
XRInputDevice rightHandDevice = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
if (rightHandDevice.isValid)
{
    //取值范围 [-1,1]
    //摇杆推到最上面时返回1,推到最下面时返回-1
    float singleValue;
    rightHandDevice.TryReadSingleValue(InputHelpers.Button.PrimaryAxis2DUp, out singleValue);
}  

XRController

  建议使用ActionBasedController代替XRController。与ActionBasedController相比,此行为不需要那么多的初始设置,但是输入处理的可定制性较低,并且XRDeviceSimulator不能用于驱动此行为。

22222.png


创建 UI Canvas

创建UICanvas.png
会同时自动创建 UI Event System

XR UI输入模块(XR UI Input Module)

设置要使用的输入处理系统
[Edit]->Project Settings->Player->Active Input Handling
1111.png

XR UI Input Module 是与 Event System 关联所必须的组件。 XR UI Input Module 与 XR Ray Interactor(XR射线交互器)协同工作,以确保正确处理与UI的XRI交互。 它还处理来自其他非XR源(如游戏板或鼠标)的输入(如果配置为这样做)。

XRUIInputModule.png

Enable Builtin Actions As Fallback
如果勾选,这将允许默认的鼠标、游戏板或操纵杆操作在当前输入系统设备配置的情况下驱动UI。

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容