一.前言
当我们接入XR Interaction Toolkit之后,我们可以很方便的做不同VR设备的适配,这在很大程度上提升了我们的开发效率,我们除了通过射线和物体交互之外,偶尔我们也会希望监听手柄上的部分按键的点击事件,今天我们就来实现如何监听VR手柄的按钮事件。
二.准备工作
我们需要准备好Unity2021工程和环境配置
有了前文:Unity之OpenXR+XR Interaction Toolkit基本配置的介绍,我们就不在详细说明这些了,大家自行复习。
流程简述:
我们新建一个3D(URP)工程
然后通过PackageManager安装XR Interaction ToolKit插件。
配置好XR Interaction Toolkit的Preset
新建一个3D场景
准备工作完毕
三.新建XR-Origin
我们通过菜单创建XR-Origin (VR)
然后找到手柄节点LeftHandController或者RightHandController,如下图所示:
我们看到XR Controller(Action-based)组件,我们获取手柄按键点击就需要用到它。
四.监听Trigger键按下事件
我们新建一个脚本,如XRInputEvent.cs 。把它添加到RightHandControler的游戏对象上。
我们先来看一下VR手柄按钮监听的基本逻辑:
//获取ActionBasedController
m_ActionController = GetComponent<ActionBasedController>();
//判断Active是否触发
var pressed = m_ActionController.activateAction.action.IsPressed();
if(pressed)
{
Debug.Log("用户按下了trigger键")
}
Active行为在InputSystem中配置的是Trigger键,如下图所示
其他按钮监听方法类似,如下所示:
//active事件:trigger按键
m_ActionController.activateAction.action.IsPressed();
//select事件:grab按键
m_ActionController.selectAction.action.IsPressed();
//ui点击事件:trigger按键
m_ActionController.uiPressAction.action.IsPressed();
//左右旋转事件:遥感的左右
m_ActionController.rotateAnchorAction.action.IsPressed();
//移动事件:遥感的前后
m_ActionController.translateAnchorAction.action.IsPressed();
五.监听Trigger键瞬时事件
我们注意到,ActionController对按钮的检测是通过按钮状态判断的,所以我们必须要在Update中检测按钮状态才行。
所以我们可以优化一下代码:
public class XRInputEvent : MonoBehaviour
{
private ActionBasedController m_ActionController;
public bool m_LastPressed;
public bool m_CurrPressed;
void Awake()
{
m_ActionController = GetComponent<ActionBasedController>();
}
void Update()
{
if (m_ActionController == null)
return;
m_CurrPressed = m_ActionController.activateAction.action.IsPressed();
if (m_CurrPressed == m_LastPressed)
return;
m_LastPressed = m_CurrPressed;
if (m_CurrPressed)
//按下
else
//抬起
}
}
优化完代码后,我们通过LastPressed和CurrPressed来实现了按下和抬起的瞬间事件。
似乎OpenXR并没有给我们提供这种类似的瞬时事件,不过我们就需要自己实现。
六.自定义事件绑定
//独立一个XRInputEvent的组件,方便外部使用
public class XRInputEvent : MonoBehaviour
{
private ActionBasedController m_ActionController;
public bool m_LastPressed;
public bool m_CurrPressed;
//新建按下事件和抬起事件,方便外部监听
public UnityEvent OnTriggerButtonDown = new UnityEvent();
public UnityEvent OnTriggerButtonUp = new UnityEvent();
void Awake()
{
m_ActionController = GetComponent<ActionBasedController>();
}
void Update()
{
if (m_ActionController == null)
{
return;
}
m_CurrPressed = m_ActionController.activateAction.action.IsPressed();
if (m_CurrPressed == m_LastPressed)
{
return;
}
m_LastPressed = m_CurrPressed;
if (m_CurrPressed)
{
OnTriggerButtonDown?.Invoke();
}
else
{
OnTriggerButtonUp?.Invoke();
}
}
}
七.使用事件绑定
有了XRInputEvent组件,我们就可以随时监听VR手柄的按键点击和抬起事件了。
如下所示:
public class VRHandItem : HandItem
{
private XRInputEvent m_XrInputEvent;
protected override void Start()
{
m_XrInputEvent = gameObject.GetOrAddComponent<XRInputEvent>();
m_XrInputEvent.OnTriggerButtonDown.AddListener(OnTriggerButtonDown);
m_XrInputEvent.OnTriggerButtonUp.AddListener(OnTriggerButtonUp);
}
protected void OnTriggerButtonDown()
{
//按下Trigger键
}
protected void OnTriggerButtonUp()
{
//抬起Trigger键
}
}