插件HTC.UnityPlugin基於SteamVR插件,可以在 Assets Store 搜索HTC.UnityPlugin,免費下載;
使用該插件需要先導入SteamVR插件,也可以在 Assets Store 搜索 SteamVR,免費下載。
HTC.UnityPlugi的優勢:相對於Steamvr來說,方便獲取手柄按鍵、方便與UGUI進行交互
首先
導入SteamVR插件,若SteamVR版本為2.0以上,依次點擊如下按鈕
之后,導入HTC.UnityPlugin插件
PS:HTC.UnityPlugin自帶示例場景位置:HTC.UnityPlugin - ViveInputUtility - Examples - 下級目錄0至7文件夾內,每個文件夾含一個示例
HTC.UnityPlugin自帶 預 制 體 位置:HTC.UnityPlugin - ViveInputUtility - Prefabs
認識手柄按鍵
VR視角
刪除場景中自帶的Main Camera,將預制體ViveRig拖入大場景中
抓取物體
1. 被抓取的物體需帶有碰撞器
2. 在被抓取的物體上添加腳本 BasicGrabbable
PS:物體B、C、D、E……是物體A的父物體
物體A掛載腳本BasicGrabbable,子物體不掛載該腳本
移動 B、C、D、E……任何一個物體,物體A下的所以子物體均會同步移動
物體A掛載腳本BasicGrabbable,子物體也掛載該腳本
只有在移動物體A時,物體A下的所以子物體才會同步移動,移動其中一個子物體時,其父物體和其余子物體不會跟着移動
若需要物體在放手之后做物理運動,則需要給物體添加Rigidbody組件
若需要拿起物體之后隱藏手部模型,需要給腳本BasicGrabbable賦值,並選擇方法,如下圖:
PS:獲得射線檢測到的物體
玩家移動
1. 在要移動的地面上添加腳本Teleportable,賦值方法如下:
2. 運行程序,按住TouchPad出現釣魚線;松開按鍵后移動到釣魚線落下的位置
PS:將可以移動的區域放在同一個父物體下,給這個父物體添加Teleportable腳本,那么這些區域就都可以移動。
射線移動物體
1. 將預制體 VivePointers 拖入場景中,作為ViveRig的子物體,並把TransFrom Rest;
2. 在被移動的物體上添加腳本 Draggable。
射線點擊UGUI
1. 射線出現的方式
(1)按 Menu 鍵會出現與UI交互的射線,但此時手柄碰撞器消失,不能進行碰撞檢測;再次按 Menu 鍵,與UI交互的射線消失,此時手柄可以進行碰撞檢測;
(2)將預制體 VivePointers 拖入場景中,作為ViveRig的子物體,並把TransFrom Rest,射線會一直出現,並且手柄也可以進行射線檢測;
2. 創建一個UI,如:Button;
3. 在Canvas面板添加腳本 CanvasRaycastTarget;
4. 刪除場景中的游戲物體“EventSystem”(經測試不刪也沒有問題,但是在運行時程序會自動創建一個 EventSystem ,最好還是刪掉)。
替換手柄模型
1. 設置預制體屬性:ViveRig - ViveControllers - Right - RenderModel - DeviceTracker - OpenVRRenderModel 的腳本“RenderModelHook”,將 OverrideModel 設置為 IndexHMD(OverrideModel中有多種模型可供選擇,可以在運行情況下嘗試)
2. 把要替換的模型作為OpenVRRenderModel的子物體(如果第一步不選擇IndexHMD,那么要替換的模型會和手柄模型一起出現)
設置釣魚線
以右手為例:
線:ViveRig - ViveControllers - Right - CurvePointer - GuideLine
落地點:ViveRig - ViveControllers - Right - CurvePointer - Reticle - Puramid - default
可通過上述屬性,設置釣魚線的材質、網格
設置釣魚線的遠近:ViveRig - ViveControllers - Right - CurvePointer - StablizedDeviceTracker - Caster 的腳本“ProjectileGenerator”的屬性:Velocity
替換UI交互射線
相對於預制體:VivePointers
射線的位置:VivePointers - Right - Reticle - GuideLine
終點小球的位置:VivePointers - Right - Reticle - Sphere - Mesh
終點小球的材質:VivePointers - Right - Reticle 的腳本 ReticlePoser 的屬性 DefaultReticleMat
可通過上述屬性,設置釣魚線的材質、網格
相對於預制體:ViveRig
射線的位置:ViveRig - ViveControllers - Right - Laser Pointer - Reticle - GuideLine
終點小球的位置:ViveRig - ViveControllers - Right - Laser Pointer - Reticle - Sphere - Mesh
可通過上述屬性,設置釣魚線的材質、網格
得到手柄按鍵
可以復制代碼到工程中進行測試,自行領會;注意,腳本名和類名一致:TestHandKey
using System.Collections; using System.Collections.Generic; using UnityEngine; // 引入該命名空間 using HTC.UnityPlugin.Vive; public class TestHandKey : MonoBehaviour { // 給按鍵添加事件(以 Menu 為例) private void Awake() { #if false // 按住不放:右手的 Menu鍵 調用方法一 ViveInput.AddPress(HandRole.RightHand, ControllerButton.Menu, One); // 按下:右手的 Menu鍵 調用方法二 ViveInput.AddPressDown(HandRole.RightHand, ControllerButton.Menu, Two); // 點擊:右手的 Menu鍵 調用方法三(點擊:按下之后立刻抬起才會響應,按住不放 一段時間后再放開,則不會調用) ViveInput.AddClick(HandRole.RightHand, ControllerButton.Menu, Three); #endif } // 方法一 private void One() { print("調用了 方法一"); } // 方法二 private void Two() { print("調用了 方法二"); } // 方法三 private void Three() { print("調用了 方法三"); } // 測試按鍵的按下、按住、抬起 private void Update() {
#if false // 打印 Trigger 的返回值 print("Trigger的返回值為:" + ViveInput.GetTriggerValue(HandRole.RightHand, false)); // 打印 Pad 的坐標值 print("Pad的坐標:" + ViveInput.GetPadAxis(HandRole.RightHand, false)); #endif #if true // Menu if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.Menu)) { print("右手 - Menu - 按下"); } else if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Menu)) { print("右手 - Menu - 按住不放"); } else if (ViveInput.GetPressUp(HandRole.RightHand, ControllerButton.Menu)) { print("右手 - Menu - 抬起"); } // Trigger if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.Trigger)) { print("右手 - Trigger - 按下"); } else if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Trigger)) { print("右手 - Trigger - 按住不放"); } else if (ViveInput.GetPressUp(HandRole.RightHand, ControllerButton.Trigger)) { print("右手 - Trigger - 抬起"); } // pad(是否觸摸到pad,通過判斷GetPadAxis的返回時是否是(0,0)來判斷) if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.Pad)) { print("右手 - Pad - 按下"); } else if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Pad)) { print("右手 - Pad - 按住不放"); } else if (ViveInput.GetPressUp(HandRole.RightHand, ControllerButton.Pad)) { print("右手 - Pad - 抬起"); } // Grip if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.Grip)) { print("右手 - Grip - 按下"); } if (ViveInput.GetPress(HandRole.RightHand, ControllerButton.Grip)) { print("右手 - Grip - 按住不放"); } if (ViveInput.GetPressUp(HandRole.RightHand, ControllerButton.Grip)) { print("右手 - Grip - 抬起"); } #endif #if false // Trigger 輕按、重按、按到底 if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.HairTrigger)) { print("Trigger - 輕按"); } else if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.Trigger)) { print("Trigger - 重按"); } else if (ViveInput.GetPressDown(HandRole.RightHand, ControllerButton.FullTrigger)) { print("Trigger - 按到底"); } #endif #if false // GetPadTouchAxis:觸摸 就會返回坐標值 print(ViveInput.GetPadTouchAxis(HandRole.RightHand)); // 從左向右滑,橫坐標為正; 從右向左滑,橫坐標為負; 從下向上滑,縱坐標為正; 從上向下滑,縱坐標為負 print(ViveInput.GetPadTouchDelta(HandRole.RightHand)); // GetPadTouchVector:以開始觸摸點為(0,0),若觸摸點為pad的最下方,當手指滑到最上方時坐標值為(0,2) print(ViveInput.GetPadTouchVector(HandRole.RightHand)); // GetPadTouchAxis 為觸摸反饋;GetPadPressAxis 為按住反饋 print(ViveInput.GetPadPressAxis(HandRole.RightHand)); print(ViveInput.GetPadPressDelta(HandRole.RightHand)); print(ViveInput.GetPadPressVector(HandRole.RightHand)); #endif } }