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()
    {
    }
}

 

posted @ 2022-12-30 14:09  朋丶Peng  阅读(684)  评论(0编辑  收藏  举报