SteamVR Plgins的使用(一)
本章节主要讲解使用SteamVR Plugins插件为基础,来介绍Vive开发的入门,重点讲解设备的激活和控制接口。SteamVR Plugins在unity官方资源商店可以免费下载,这里我就不给出链接了。
导入SteamVR Plugins后,不要在他的示例上去做开发,那样你会走弯路。因为这个插件的设备初始化代码很怪异,甚至可以说无法使用。因此我们需要自己写设备的初始化代码以及设备的操作接口。
我们对原插件进行封装后就可以愉快的使用了,之后怎么开发就和这个设备无关了,我们开发这类的应用无非是获取相关的接口操作。
新建场景,然后在Camera上添加组件SteamVR_Camera,然后点击 Expand 按钮,之后我们就得到了一个基本的VR相机。
然后我们在Camera的下面新建两个GameObject,并命名为LeftHand和RightHand。同时添加组件SteamVR_TrackedObject。然后在各自的下面添加一个对象名为Mode,并绑定组件SteamVR_RenderModel。
如果对这些步骤有疑问,可以查看百度文库按照上面的操作完成基本的对象搭建操作:http://wenku.baidu.com/view/eaaec2f058fb770bf68a55b1.html
接下来就是开始撸代码了,新建脚本SteamVR_InitManager.cs,来获取手柄的激活和相关的初始化代码。
using UnityEngine; using System.Collections; using Valve.VR; using System; public class SteamVR_InitManager : MonoBehaviour { public event Action<SteamVR_TrackedObject> OnLeftDeviceActive;//左手柄激活事件 public event Action<SteamVR_TrackedObject> OnRightDeviceActive;//右手柄激活事件 public SteamVR_TrackedObject LeftObject; public SteamVR_TrackedObject RightObject; private bool[] isAllConnect;//0代表右手状态,1代表左手状态 private uint leftIndex = 100;//左手柄对应的设备ID private uint rightIndex = 100;//右手柄对应的设备ID private static SteamVR_InitManager instance; public DeviceInput LeftHandInput; public DeviceInput RightHandInput; public static SteamVR_InitManager Instance { get { if (instance == null) { instance = GameObject.FindObjectOfType<SteamVR_InitManager>(); } return instance; } } // Use this for initialization void Awake() { LeftObject = transform.FindChild("LeftHand").GetComponent<SteamVR_TrackedObject>(); RightObject = transform.FindChild("RightHand").GetComponent<SteamVR_TrackedObject>(); LeftObject.gameObject.SetActive(false); RightObject.gameObject.SetActive(false); } void Start() { StartCoroutine(CheckDeviceActive()); } void OnEnable() { OnLeftDeviceActive += LeftDeviceActive; OnRightDeviceActive += RightDeviceActive; } void OnDisable() { OnLeftDeviceActive -= LeftDeviceActive; OnRightDeviceActive -= RightDeviceActive; } /// <summary> /// 检测手柄设备是否激活 /// </summary> /// <returns></returns> IEnumerator CheckDeviceActive() { yield return new WaitForSeconds(1); while (!isAllConnect[0] || !isAllConnect[1]) { for (uint i = 1; i < OpenVR.k_unMaxTrackedDeviceCount; i++) { if (i == leftIndex || i == rightIndex) continue;//已经初始化的不再进入判断 if (OpenVR.System != null && OpenVR.System.IsTrackedDeviceConnected(i)) { OnDeviceConnected(new object[] { i, true }); } } yield return new WaitForFixedUpdate(); } yield return 0; } /// <summary> /// 检测激活的设备是否是手柄 /// </summary> /// <param name="args"></param> private void OnDeviceConnected(object[] args) { if (args != null && args.Length > 1) { uint index = (uint)args[0]; bool isConnect = (bool)args[1]; var system = OpenVR.System; if (isConnect && system != null && system.GetTrackedDeviceClass(index) == ETrackedDeviceClass.Controller) { uint tmpleftIndex = (uint)system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand); uint tmprightIndex = (uint)system.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand); if (index == tmprightIndex) { isAllConnect[0] = true; rightIndex = index; OnRightDeviceActive(RightObject); } else if (index == tmpleftIndex) { isAllConnect[1] = true; leftIndex = index; OnLeftDeviceActive(LeftObject); } } } } private void RightDeviceActive(SteamVR_TrackedObject obj) { DeviceActive(obj, rightIndex); RightHandInput = obj.GetComponent<DeviceInput>(); } private void LeftDeviceActive(SteamVR_TrackedObject obj) { DeviceActive(obj, leftIndex); LeftHandInput = obj.GetComponent<DeviceInput>(); } /// <summary> /// 匹配对应的设备号,完成手柄模型的设置 /// </summary> /// <param name="device"></param> /// <param name="index"></param> void DeviceActive(SteamVR_TrackedObject device, uint index) { SteamVR_TrackedObject.EIndex eIndex = (SteamVR_TrackedObject.EIndex)Enum.Parse(typeof(SteamVR_TrackedObject.EIndex), "Device" + index); device.index = eIndex; device.GetComponentInChildren<SteamVR_RenderModel>().index = eIndex; device.gameObject.SetActive(true); } }
然后就是大家比较关心的手柄控制接口代码DeviceInput.cs,我基本上把所有的手柄控制事件都写完了.
using UnityEngine; using System.Collections; using System; using Valve.VR; public class DeviceInput : MonoBehaviour { //Swipe directions public enum SwipeDirection { NONE, UP, DOWN, LEFT, RIGHT }; public event Action OnPressTrigger; //按住扳机键 public event Action OnPressDownTrigger; // 按下扳机键 public event Action OnPressUpTrigger; //抬起扳机键 public event Action OnTouchPad; //按住触摸板 public event Action OnPressDownGripButton; //按下侧键 public event Action OnPressDownMenuButton; //按下菜单键 public event Action<Vector2> OnBeginTouch; //触摸触摸板的位置 public event Action<Vector2> OnEndTouch;//抬起触摸板的位置 public event Action OnTouchPadDown; //按下触摸板 public event Action OnTouchPadUp;//抬起触摸板 public event Action<SwipeDirection> OnPadSwipe; [SerializeField] private float m_SwipeWidth = 0.6f; //The width of a swipe private Vector2 m_PadDownPosition; private float m_LastHorizontalValue; private float m_LastVerticalValue; private SteamVR_TrackedObject Hand; private SteamVR_Controller.Device device; private Vector2 m_PadPosition; public void Start() { Hand = GetComponent<SteamVR_TrackedObject>(); } public void Update() { CheckInput(); } private void CheckInput() { // Set the default swipe to be none. SwipeDirection swipe = SwipeDirection.NONE; if (device == null) { device = SteamVR_Controller.Input((int)Hand.index); print("NUll Device"); return; } if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Trigger)) { if (OnPressTrigger != null) OnPressTrigger(); } if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger)) { if (OnPressDownTrigger != null) OnPressDownTrigger(); } if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) { if (OnPressUpTrigger != null) OnPressUpTrigger(); } if (device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad)) { if (OnTouchPad != null) OnTouchPad(); m_PadPosition = device.GetAxis(); } if (device.GetTouchUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) { if (OnTouchPadUp != null) OnTouchPadUp(); if (OnEndTouch != null) OnEndTouch(m_PadPosition); swipe = DetectSwipe(); m_PadDownPosition = Vector2.zero; } if (device.GetTouchDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) { if (OnTouchPadDown != null) OnTouchPadDown(); if (OnBeginTouch != null) OnBeginTouch(m_PadDownPosition = device.GetAxis()); } if (device.GetPressDown(EVRButtonId.k_EButton_Grip)) { if (OnPressDownGripButton != null) { OnPressDownGripButton(); } } if (device.GetPressDown(EVRButtonId.k_EButton_ApplicationMenu)) { if (OnPressDownMenuButton != null) OnPressDownMenuButton(); } if (swipe != SwipeDirection.NONE) { OnPadSwipe(swipe); if (device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad)) { m_PadPosition = device.GetAxis(); } else { m_PadDownPosition = Vector2.zero; } } } private SwipeDirection DetectSwipe() { Vector2 swipeData = (m_PadPosition - m_PadDownPosition).normalized; bool swipeIsVertical = Mathf.Abs(swipeData.y) > m_SwipeWidth; bool swipeIsHorizontal = Mathf.Abs(swipeData.x) > m_SwipeWidth; if (swipeData.y > 0f && swipeIsVertical) return SwipeDirection.UP; if (swipeData.y < 0f && swipeIsVertical) return SwipeDirection.DOWN; if (swipeData.x > 0f && swipeIsHorizontal) return SwipeDirection.RIGHT; if (swipeData.x < 0f && swipeIsHorizontal) return SwipeDirection.LEFT; return SwipeDirection.NONE; } public void OnDisEnable() { OnPressTrigger = null; //按住扳机键 OnPressDownTrigger = null; // 按下扳机键 OnPressUpTrigger = null; //抬起扳机键 OnTouchPad = null; //按住触摸板 OnPressDownGripButton = null; //按下侧键 OnPressDownMenuButton = null; //按下菜单键 OnBeginTouch = null; //触摸触摸板的位置 OnEndTouch = null;//抬起触摸板的位置 OnTouchPadDown = null; //按下触摸板 OnTouchPadUp = null;//抬起触摸板 OnPadSwipe = null; } }
OK,接下来写一个简单的测试类来测试相关的代码:
using UnityEngine; using System.Collections; using System; /// <summary> /// 这是一个测试类,简单的测试了手柄的激活以及部分手柄的操作事件 /// 两个手柄分开注册,这样扩展性非常好,相同的按键可以做不同的处理 /// 大家可以补充测试 /// </summary> public class TestEvent : MonoBehaviour { void OnEnable() { SteamVR_InitManager.Instance.OnLeftDeviceActive += OnLeftDeviceActive;//左手柄激活 SteamVR_InitManager.Instance.OnRightDeviceActive += OnRightDeviceActive;//右手柄激活 } private void OnRightDeviceActive(SteamVR_TrackedObject obj) { print("OnRightDeviceActive"+obj); SteamVR_InitManager.Instance.RightHandInput.OnPressDownTrigger += OnPressDownTrigger; SteamVR_InitManager.Instance.RightHandInput.OnTouchPadDown += OnTouchPadDown; } private void OnPressDownTrigger() { print("OnPressDownTrigger"); } private void OnTouchPadDown() { print("OnTouchPadDown"); } private void OnLeftDeviceActive(SteamVR_TrackedObject obj) { print("OnLeftDeviceActive" + obj); SteamVR_InitManager.Instance.LeftHandInput.OnPressDownTrigger += OnPressDownTrigger; SteamVR_InitManager.Instance.LeftHandInput.OnTouchPadDown += OnTouchPadDown; } void OnDisable() { SteamVR_InitManager.Instance.OnLeftDeviceActive -= OnLeftDeviceActive;//左手柄激活 SteamVR_InitManager.Instance.OnRightDeviceActive -= OnRightDeviceActive;//右手柄激活 } }
下一章我主要介绍手柄和射线事件的相结合代码,以及抛物线的绘制和移动,欢迎大家关注