UnityXR Pico和HTCVive判断手柄连没连接上
方法一:用InputDevices.GetDevices(),PICO中使用的此方法
此方法获取当前连接的设备:
1.在Pico中连上哪个手柄就有哪个手柄,正常使用。
2.PC端HTCVive上不正常:
InputDevices.GetDevices()方法会获取到所有连接过的设备,即使设备已断开:
运行程序的时候两个手柄都连上,此方法获取的设备列表就会一直有这两个手柄,
即使手柄断开,只有重启电脑或者STEAMVR,从方法获取到的就是当前连接的设备,
总之,在重启电脑或者STEAMVR的情况下,程序运行时连接过的设备都会被获取到,
即使再断开设备;
方法二:判断手柄模型LeftBaseController和RightBaseController的本地位置是不是(0,0,0)
1.在Pico中连上哪个手柄就有哪个手柄,正常使用。
2.PC端HTCVive上不正常:
当手柄连接时这两个物体的位置肯定不是(0,0,0),即使用户特意拿着手柄往(0,0,0)去对,也对不准确,
但是这样也有问题。
在HTCVive中左手柄会变为右手柄:
两个手柄都连接时,断开右手柄,右手柄模型正常隐藏,左手柄正常使用,先断开左手柄,左手柄模型正常隐藏,右手柄也能正常使用,
两个手柄都没连接时,先连接上右手柄再连接上左手柄,也能正常使用,对应的模型也对,
两个手柄都没连接时,先连接上左手柄,左手柄就会先是左手柄(有左手柄模型),
然后突然变为变为右手柄(同时在左手柄模型位置出现一个右手柄模型,左手柄模型就会一直在那个位置),
此时如果不连接右手柄,刚才的连接的手柄就可以当右手柄正常使用,但是左手柄模型会一直在那,如果再连接上右手柄,
右手柄就会是左手柄(右手柄会对应上左手柄的模型),此时就是左右手柄互换了,也能正常使用了;
方法三:0.5秒获取一次模型位置,如果和上一次位置一样,就隐藏
能正常使用
本来想的是如果用方法三,那么手柄连接上,但是放在桌子上不去动,0.5秒后它就会被隐藏,但没办法,前两个方法都不行,只能用这个。
但是实际上只有手柄没连接的时候模型不动,0.5秒后隐藏,手柄连接时放桌子上不动,0.5秒后并不会消失,不知道具体是什么原因,
猜测是定位器不可能完全百分百准确定位,假如把手柄放到(1f,2f,3f)的位置不动,可能定位器定位手柄的位置的值每次都不一样,
比如(1.001f,1.998,3.002f)等会有微小偏差。
代码在JudgeDevicesValid()方法中:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; using UnityEngine.XR.Interaction.Toolkit; public class GetKeyEvent : MonoBehaviour { InputDevice m_RightController; InputDevice m_LeftController; private Dictionary<int, bool> keyPressDic = new Dictionary<int, bool>(); bool[] arrayL = new bool[22]; bool[] arrayR = new bool[22]; bool[] lockArrayL = new bool[22]; bool[] lockArrayR = new bool[22]; public static GetKeyEvent instance; public List<InputDevice> devices = new List<InputDevice>(); public GameObject l_ControllerDevice; public GameObject r_ControllerDevice; string l_ControllerName = "PicoXR Controller-Left"; string r_ControllerName = "PicoXR Controller-Right"; Vector3 l_LastPos = new Vector3(); Vector3 r_LastPos = new Vector3(); private void Awake() { if (instance == null) { instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } // Start is called before the first frame update void Start() { l_LastPos = Vector3.zero; r_LastPos = Vector3.zero; InitDic(); InputDevices.deviceConnected += RegisterDevices; var devices = new List<InputDevice>(); InputDevices.GetDevices(devices); foreach (var device in devices) RegisterDevices(device); StartCoroutine(JudgeDevicesValid()); } // Update is called once per frame void Update() { if (isPressKeyL(InputHelpers.Button.TriggerButton) || isPressKeyR(InputHelpers.Button.TriggerButton)) { //Debug.Log("Trigger button is pressed."); } } void RegisterDevices(InputDevice connectedDevice) { Debug.LogError("RegisterDevices()方法:" + connectedDevice.name + " " + connectedDevice.isValid); if (connectedDevice.isValid) { #if UNITY_2019_3_OR_NEWER if ((connectedDevice.characteristics & InputDeviceCharacteristics.Left) != 0) #else if (connectedDevice.role == InputDeviceRole.LeftHanded) #endif { m_LeftController = connectedDevice; } #if UNITY_2019_3_OR_NEWER else if ((connectedDevice.characteristics & InputDeviceCharacteristics.Right) != 0) #else else if (connectedDevice.role == InputDeviceRole.RightHanded) #endif { m_RightController = connectedDevice; } } } /// <summary> /// 判断手柄连接状态 /// </summary> /// <returns></returns> IEnumerator JudgeDevicesValid() { while (true) { yield return new WaitForSeconds(0.5f); devices = new List<InputDevice>(); InputDevices.GetDevices(devices); #if UNITY_EDITOR l_ControllerDevice.SetActive(true); r_ControllerDevice.SetActive(true); #elif UNITY_STANDALONE_WIN /*l_ControllerDevice.transform.Find("ModelPt").gameObject.SetActive(l_ControllerDevice.transform.localPosition != Vector3.zero); l_ControllerDevice.GetComponent<XRInteractorLineVisual>().enabled = l_ControllerDevice.transform.localPosition != Vector3.zero; r_ControllerDevice.transform.Find("ModelPt").gameObject.SetActive(r_ControllerDevice.transform.localPosition != Vector3.zero); r_ControllerDevice.GetComponent<XRInteractorLineVisual>().enabled = r_ControllerDevice.transform.localPosition != Vector3.zero;*/ //HTC Vive if(l_ControllerDevice.transform.localPosition != l_LastPos) { l_ControllerDevice.transform.Find("ModelPt").gameObject.SetActive(true); l_ControllerDevice.GetComponent<XRInteractorLineVisual>().enabled = true; l_LastPos = l_ControllerDevice.transform.localPosition; } else { l_ControllerDevice.transform.Find("ModelPt").gameObject.SetActive(false); l_ControllerDevice.GetComponent<XRInteractorLineVisual>().enabled = false; } if (r_ControllerDevice.transform.localPosition != r_LastPos) { r_ControllerDevice.transform.Find("ModelPt").gameObject.SetActive(true); r_ControllerDevice.GetComponent<XRInteractorLineVisual>().enabled = true; r_LastPos = r_ControllerDevice.transform.localPosition; } else { r_ControllerDevice.transform.Find("ModelPt").gameObject.SetActive(false); r_ControllerDevice.GetComponent<XRInteractorLineVisual>().enabled = false; } #else //Pico l_ControllerDevice.SetActive(devices.Find(temp => temp.name == l_ControllerName).isValid); r_ControllerDevice.SetActive(devices.Find(temp => temp.name == r_ControllerName).isValid); #endif } } public bool isPressKeyL(InputHelpers.Button button) { if (!arrayL[((int)button)]) { lockArrayL[((int)button)] = false; } if (m_LeftController.IsPressed(button, out arrayL[((int)button)]) && arrayL[((int)button)] && !lockArrayL[((int)button)]) { lockArrayL[((int)button)] = true; return true; } else { return false; } } public bool isPressKeyR(InputHelpers.Button button) { if (!arrayR[((int)button)]) { lockArrayR[((int)button)] = false; } if (m_RightController.IsPressed(button, out arrayR[((int)button)]) && arrayR[((int)button)] && !lockArrayR[((int)button)]) { lockArrayR[((int)button)] = true; return true; } else { return false; } } private void InitDic() { for (int i = 0; i < 22; i++) { arrayR[i] = false; arrayL[i] = false; lockArrayL[i] = false; lockArrayR[i] = false; } } private void OnDisable() { } }