您现在的位置是:首页 >技术杂谈 >Unity之OpenXR+XR Interaction Toolkit实现 监听VR手柄按键网站首页技术杂谈

Unity之OpenXR+XR Interaction Toolkit实现 监听VR手柄按键

PassionY 2023-07-22 12:00:02
简介Unity之OpenXR+XR Interaction Toolkit实现 监听VR手柄按键

一.前言

当我们接入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键
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。