赞
踩
测试使用的是Unity2021.3.8和Quest2,只需绑定事件即可获取Quest各个按键状态,按下,抬起,按下中··
参考文档:
https://docs.unity3d.com/cn/current/Manual/xr_input.html
https://blog.csdn.net/Q540670228/article/details/123139150
使用以上代码时碰到些小问题(调试时获取不到设备,按钮冲突),部分内容做了修改
实现效果
全部代码
MonoSingleton.cs
using UnityEngine; namespace Common { ///<summary> ///脚本单例类,负责为唯一脚本创建实例 ///<summary> public class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T> //注意此约束为T必须为其本身或子类 { /* 相较于直接在需要唯一创建的脚本中创建实例,Awake初始化的过程需要解决的问题 1.代码重复 2.在Awake里面初始化,其它脚本在Awake中调用其可能会为Null的异常情况 */ //解决1:使用泛型创建实例 解决2:使用按需加载(即有其它脚本调用时在get中加载) private static T instance; //创建私有对象记录取值,可只赋值一次避免多次赋值 public static T Instance { //实现按需加载 get { //当已经赋值,则直接返回即可 if (instance != null) return instance; instance = FindObjectOfType<T>(); //为了防止脚本还未挂到物体上,找不到的异常情况,可以自行创建空物体挂上去 if (instance == null) { //如果创建对象,则会在创建时调用其身上脚本的Awake即调用T的Awake(T的Awake实际上是继承的父类的) //所以此时无需为instance赋值,其会在Awake中赋值,自然也会初始化所以无需init() /*instance = */ new GameObject("Singleton of " + typeof(T)).AddComponent<T>(); } return instance; } } private void Awake() { //若无其它脚本在Awake中调用此实例,则可在Awake中自行初始化instance instance = this as T; //初始化 //Init(); } } }
InputEvent.cs
//示例中此代码放到了XR Origin上面
using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; /// <summary> /// 提供各种输入事件 /// </summary> public class InputEvent : Common.MonoSingleton<InputEvent> { //*************输入设别************************** InputDevice leftHandController; InputDevice rightHandController; InputDevice headController; //**************对外提供公开事件****************** #region public event public Action onLeftTriggerEnter; public Action onLeftTriggerDown; public Action onLeftTriggerUp; public Action onRightTriggerEnter; public Action onRightTriggerDown; public Action onRightTriggerUp; public Action onLeftGripEnter; public Action onLeftGripDown; public Action onLeftGripUp; public Action onRightGripEnter; public Action onRightGripDown; public Action onRightGripUp; public Action onLeftAppButtonEnter; public Action onLeftAppButtonDown; public Action onLeftAppButtonUp; public Action onRightAppButtonEnter; public Action onRightAppButtonDown; public Action onRightAppButtonUp; public Action onLeftJoyStickEnter; public Action onLeftJoyStickDown; public Action onLeftJoyStickUp; public Action onRightJoyStickEnter; public Action onRightJoyStickDown; public Action onRightJoyStickUp; public Action<Vector2> onLeftJoyStickMove; public Action<Vector2> onRightJoyStickMove; public Action onLeftAXButtonEnter; public Action onLeftAXButtonDown; public Action onLeftAXButtonUp; public Action onLeftBYButtonEnter; public Action onLeftBYButtonDown; public Action onLeftBYButonUp; public Action onRightAXButtonEnter; public Action onRightAXButtonDown; public Action onRightAXButtonUp; public Action onRightBYButtonEnter; public Action onRightBYButtonDown; public Action onRightBYButtonUp; #endregion //提供状态字典独立记录各个feature的状态 Dictionary<string, bool> stateDic; private void Init() { if (!leftHandController.isValid) { leftHandController = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand); } if (!rightHandController.isValid) { rightHandController = InputDevices.GetDeviceAtXRNode(XRNode.RightHand); } if (!headController.isValid) { headController = InputDevices.GetDeviceAtXRNode(XRNode.Head); } stateDic = new Dictionary<string, bool>(); } //*******************事件源的触发************************** /// <summary> /// 按钮事件源触发模板 /// </summary> /// <param name="device">设备</param> /// <param name="usage">功能特征</param> /// <param name="btnEnter">开始按下按钮事件</param> /// <param name="btnDown">按下按钮事件</param> /// <param name="btnUp">抬起按钮事件</param> private void ButtonDispatchModel(InputDevice device, InputFeatureUsage<bool> usage, Action btnEnter, Action btnDown, Action btnUp) { //Debug.Log("usage:" + usage.name); //为首次执行的feature添加bool状态 -- 用以判断Enter和Up状态 string featureKey = device.characteristics + usage.name; if (!stateDic.ContainsKey(featureKey)) { stateDic.Add(featureKey, false); } bool isDown; if (device.TryGetFeatureValue(usage, out isDown) && isDown) { //Debug.Log("device:" + device.characteristics + "usage:" + usage.name); if (!stateDic[featureKey]) { stateDic[featureKey] = true; btnEnter?.Invoke(); } btnDown?.Invoke(); } else { if (stateDic[featureKey]) { btnUp?.Invoke(); stateDic[featureKey] = false; } } } /// <summary> /// 摇杆事件源触发模板 /// </summary> /// <param name="device">设备</param> /// <param name="usage">功能特征</param> /// <param name="joyStickMove">移动摇杆事件</param> private void JoyStickDispatchModel(InputDevice device, InputFeatureUsage<Vector2> usage, Action<Vector2> joyStickMove) { Vector2 axis; if (device.TryGetFeatureValue(usage, out axis) && !axis.Equals(Vector2.zero)) { if (joyStickMove != null) joyStickMove(axis); } } //******************每帧轮询监听事件*********************** private void Update() { if (leftHandController.isValid) { ButtonDispatchModel(leftHandController, CommonUsages.triggerButton, onLeftTriggerEnter, onLeftTriggerDown, onLeftTriggerUp); ButtonDispatchModel(leftHandController, CommonUsages.gripButton, onLeftGripEnter, onLeftGripDown, onLeftGripUp); ButtonDispatchModel(leftHandController, CommonUsages.primaryButton, onLeftAXButtonEnter, onLeftAXButtonDown, onLeftAXButtonUp); ButtonDispatchModel(leftHandController, CommonUsages.secondaryButton, onLeftBYButtonEnter, onLeftBYButtonDown, onLeftBYButonUp); ButtonDispatchModel(leftHandController, CommonUsages.primary2DAxisClick, onLeftJoyStickEnter, onLeftJoyStickDown, onLeftJoyStickUp); ButtonDispatchModel(leftHandController, CommonUsages.menuButton, onLeftAppButtonEnter, onLeftAppButtonDown, onLeftAppButtonUp); //JoyStickDispatchModel(leftHandController, CommonUsages.primary2DAxis, onLeftJoyStickMove); } else { Init(); } if (rightHandController.isValid) { ButtonDispatchModel(rightHandController, CommonUsages.triggerButton, onRightTriggerEnter, onRightTriggerDown, onRightTriggerUp); ButtonDispatchModel(rightHandController, CommonUsages.gripButton, onRightGripEnter, onRightGripDown, onRightGripUp); ButtonDispatchModel(rightHandController, CommonUsages.primaryButton, onRightAXButtonEnter, onRightAXButtonDown, onRightAXButtonUp); ButtonDispatchModel(rightHandController, CommonUsages.secondaryButton, onRightBYButtonEnter, onRightBYButtonDown, onRightBYButtonUp); ButtonDispatchModel(rightHandController, CommonUsages.primary2DAxisClick, onRightJoyStickEnter, onRightJoyStickDown, onRightJoyStickUp); ButtonDispatchModel(rightHandController, CommonUsages.menuButton, onRightAppButtonEnter, onRightAppButtonDown, onRightAppButtonUp); //JoyStickDispatchModel(rightHandController, CommonUsages.primary2DAxis, onRightJoyStickMove); } else { Init(); } } }
使用示例
LeftHandButton.cs
//示例中此代码放到了LeftHand Controller上面
using UnityEngine; public class LeftHandButton : MonoBehaviour { private void Awake() { InputEvent.Instance.onLeftAXButtonUp += LeftAXButtonUp; InputEvent.Instance.onLeftAXButtonEnter += LeftAXButtonEnter; InputEvent.Instance.onLeftAXButtonDown += LeftAXButtonDown; } void LeftAXButtonDown() { print("左手柄A键按下中···"); } void LeftAXButtonEnter() { print("按下左手柄A键"); } void LeftAXButtonUp() { print("抬起左手柄A键"); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。