方法一:用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()
{
}
}