SteamVR Plgins的使用(一)

本章节主要讲解使用SteamVR Plugins插件为基础,来介绍Vive开发的入门,重点讲解设备的激活和控制接口。SteamVR Pluginsunity官方资源商店可以免费下载,这里我就不给出链接了。

导入SteamVR Plugins后,不要在他的示例上去做开发,那样你会走弯路。因为这个插件的设备初始化代码很怪异,甚至可以说无法使用。因此我们需要自己写设备的初始化代码以及设备的操作接口。

我们对原插件进行封装后就可以愉快的使用了,之后怎么开发就和这个设备无关了,我们开发这类的应用无非是获取相关的接口操作。

新建场景,然后在Camera上添加组件SteamVR_Camera,然后点击 Expand 按钮,之后我们就得到了一个基本的VR相机。

然后我们在Camera的下面新建两个GameObject,并命名为LeftHandRightHand。同时添加组件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;//右手柄激活
    }
}

 

  下一章我主要介绍手柄和射线事件的相结合代码,以及抛物线的绘制和移动,欢迎大家关注

 

 

原文地址:https://www.cnblogs.com/jqg-aliang/p/5731237.html