如何开发一款VR游戏,实现输入交互至关重要,我们先来看看在unity中如何对vive手柄进行编程,包括对手柄圆盘的使用说法。
第一步,导入steamVR 插件和认识手柄:
 如图,我们已经导入了SteamVR Plugin,下面的SteamVR绿色图标表明Htc Vive的硬件也已经准备就绪,这是SteamVR_TestThrow场景,也是我们展开分析的入手点.这个测试很简单,就是你按下Trigger的时候,手柄上会实例化一个圆球+cube的结合体,当然松开Trigger的时候这个结合体就会脱离手柄,当然,你还可以施加一个扔的动作,这样的话结合体会有一个对应的加速度。
手柄是HTC Vive的重要交互手段,我们通过第一个图片应该对其有一个直观的了解了,总共是九个按钮:

  • 第一个是菜单按钮;
  • 2,3,4,5分别对应的是Trackpad/Touchpad的上下左右,有时候对应的是XBox手柄的▲OX囗四个按钮或者摇杆;
  • 6对应的是系统按钮/Steam;
  • 7是Trigger/扳机,对应大多数FPS游戏里面的枪械的Shoot/Fire;
  • 8对应的Grip/紧握在手柄的左右两侧各有一个,有时候我们用它来翻页;
  • 9其实是Trackpad/Touchpad在Z轴的一个延伸,相当于是点击事件Click.


第二步:上代码说明如何控制:
 
比较难明白的就是那个圆盘键,这个键是一个以中心为(0,0)点的直角坐标系,四个端长度都是1,可接收触摸和按压两种事件,见上图,触摸touch或按压press会通过GetAxis方法返回一个坐标系中的点,可以判断你按在哪里,触发不同的事件,可以根据角度或各种方法来切分按键为n个按钮。

[代码]:

001 using UnityEngine; 
002 using System.Collections; 
003 //检测手柄功能的脚本 这个脚本挂到手柄上(controler(right)和controler(left))上 
004 public class ButtonTouchAction : MonoBehaviour { 
005     //手柄 
006     SteamVR_TrackedObject trackdeObjec; 
007   
008     void Awake() { 
009         //获取手柄上的这个组件 
010         trackdeObjec = GetComponent<steamvr_trackedobject>(); 
011     
012     // Use this for initialization 
013     void Start () {    
014     
015     void FixedUpdate() 
016     {   //获取手柄输入 
017         var device = SteamVR_Controller.Input((int)trackdeObjec.index); 
018         //以下是api中复制出来的按键列表 
019         /*       public class ButtonMask
020            {
021                public const ulong System = (1ul << (int)EVRButtonId.k_EButton_System); // reserved
022                public const ulong ApplicationMenu = (1ul << (int)EVRButtonId.k_EButton_ApplicationMenu);
023                public const ulong Grip = (1ul << (int)EVRButtonId.k_EButton_Grip);
024                public const ulong Axis0 = (1ul << (int)EVRButtonId.k_EButton_Axis0);
025                public const ulong Axis1 = (1ul << (int)EVRButtonId.k_EButton_Axis1);
026                public const ulong Axis2 = (1ul << (int)EVRButtonId.k_EButton_Axis2);
027                public const ulong Axis3 = (1ul << (int)EVRButtonId.k_EButton_Axis3);
028                public const ulong Axis4 = (1ul << (int)EVRButtonId.k_EButton_Axis4);
029                public const ulong Touchpad = (1ul << (int)EVRButtonId.k_EButton_SteamVR_Touchpad);
030                public const ulong Trigger = (1ul << (int)EVRButtonId.k_EButton_SteamVR_Trigger);
031            }
032            */
033   
034            //同样是三种按键方式,以后不做赘述 
035         if (device.GetTouch(SteamVR_Controller.ButtonMask.Trigger)) { 
036             Debug.Log("按了 “trigger” “扳机键”"); 
037              
038             //右手震动 
039             //拉弓类似操作应该就是按住trigger(扳机)gettouch时持续调用震动方法模拟弓弦绷紧的感觉。 
040             var deviceIndex2 = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Rightmost); 
041             SteamVR_Controller.Input(deviceIndex2).TriggerHapticPulse(500); 
042   
043         
044         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger)) 
045         {   Debug.Log("按下了 “trigger” “扳机键”"); 
046   
047         
048         if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger)) { 
049             Debug.Log("松开了 “trigger” “扳机键”"); 
050             
051             //左手震动 
052             var deviceIndex = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Leftmost); 
053             SteamVR_Controller.Input(deviceIndex).TriggerHapticPulse(3000); 
054              
055             //右手震动 
056             var deviceIndex1 = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Rightmost); 
057             SteamVR_Controller.Input(deviceIndex1).TriggerHapticPulse(3000); 
058         
059   
060         //这三种也能检测到 后面不做赘述 
061         if(device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger)) { 
062             Debug.Log("用press按下了 “trigger” “扳机键”"); 
063         
064         if (device.GetPress(SteamVR_Controller.ButtonMask.Trigger)) 
065         
066             Debug.Log("用press按了 “trigger” “扳机键”"); 
067         
068         if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger)) 
069         
070             Debug.Log("用press松开了 “trigger” “扳机键”"); 
071         
072   
073         //system键 圆盘下面那个键  
074         // reserved 为Steam系统保留,用来调出Steam系统菜单 因此貌似自己加的功能没啥用 
075         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.System)) 
076         
077             Debug.Log("按下了 “system” “系统按钮/Steam”"); 
078         
079         if (device.GetPressDown(SteamVR_Controller.ButtonMask.System)) 
080         
081             Debug.Log("用press按下了 “System” “系统按钮/Steam”"); 
082         
083   
084         //ApplicationMenu键 带菜单标志的那个按键(在方向圆盘上面) 
085         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.ApplicationMenu)) 
086         
087             Debug.Log("按下了 “ApplicationMenu” “菜单键”"); 
088         
089         if (device.GetPressDown(SteamVR_Controller.ButtonMask.ApplicationMenu)) 
090         
091             Debug.Log("用press按下了 “ApplicationMenu” “菜单键”"); 
092         
093   
094         //Grip键 两侧的键 (vive雇佣兵游戏中的换弹键),每个手柄左右各一功能相同,同一手柄两个键是一个键。 
095         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Grip)) 
096         
097             Debug.Log("按下了 “Grip” “ ”"); 
098         
099         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Grip)) 
100         
101             Debug.Log("用press按下了 “Grip” “ ”"); 
102         
103   
104    
105           
106         //Axis0键 与圆盘有交互 与圆盘有关 
107         //触摸触发 
108         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis0)) 
109         
110             Debug.Log("按下了 “Axis0” “方向 ”"); 
111         
112         //按动触发 
113         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis0)) 
114         
115             Debug.Log("用press按下了 “Axis0” “方向 ”"); 
116         
117   
118         //Axis1键  目前未发现按键位置 
119         //触摸触发 
120         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis1)) 
121         
122             Debug.Log("按下了 “Axis1” “ ”"); 
123         
124         //按动触发  
125         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis1)) 
126         
127             Debug.Log("用press按下了 “Axis1” “ ”"); 
128         
129   
130         //Axis2键 目前未发现按键位置 
131         //触摸触发 
132         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis2)) 
133         
134             Debug.Log("按下了 “Axis2” “ ”"); 
135         
136         //按动触发 
137         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis2)) 
138         
139             Debug.Log("用press按下了 “Axis2” “ ”"); 
140         
141   
142         //Axis3键  未目前未发现按键位置 
143         //触摸触发 
144         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis3)) 
145         
146             Debug.Log("按下了 “Axis3” “ ”"); 
147         
148         //按动触发 
149         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis3)) 
150         
151             Debug.Log("用press按下了 “Axis3” “ ”"); 
152         
153   
154         //Axis4键  目前未发现按键位置 
155         //触摸触发 
156         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis4)) 
157         
158             Debug.Log("按下了 “Axis4” “ ”"); 
159         
160         //按动触发 
161         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis4)) 
162         
163             Debug.Log("用press按下了 “Axis4” “ ”"); 
164         
165
166 //方向圆盘: 
167         //这里开始区分了press检测与touch检测的不同之处,圆盘可以触摸,顾名思义,touch检测的是触摸,press检测的是按动<pre name="code" class="csharp"> //Axis0键 与圆盘有交互 与圆盘有关 
168         //触摸触发 
169         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis0)) 
170         
171             Debug.Log("按下了 “Axis0” “方向 ”"); 
172         
173         //按动触发 
174         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis0)) 
175         
176             Debug.Log("用press按下了 “Axis0” “方向 ”"); 
177         
178   
179         //Axis1键  目前未发现按键位置 
180         //触摸触发 
181         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis1)) 
182         
183             Debug.Log("按下了 “Axis1” “ ”"); 
184         
185         //按动触发  
186         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis1)) 
187         
188             Debug.Log("用press按下了 “Axis1” “ ”"); 
189         
190   
191         //Axis2键 目前未发现按键位置 
192         //触摸触发 
193         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis2)) 
194         
195             Debug.Log("按下了 “Axis2” “ ”"); 
196         
197         //按动触发 
198         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis2)) 
199         
200             Debug.Log("用press按下了 “Axis2” “ ”"); 
201         
202   
203         //Axis3键  未目前未发现按键位置 
204         //触摸触发 
205         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis3)) 
206         
207             Debug.Log("按下了 “Axis3” “ ”"); 
208         
209         //按动触发 
210         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis3)) 
211         
212             Debug.Log("用press按下了 “Axis3” “ ”"); 
213         
214   
215         //Axis4键  目前未发现按键位置 
216         //触摸触发 
217         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Axis4)) 
218         
219             Debug.Log("按下了 “Axis4” “ ”"); 
220         
221         //按动触发 
222         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Axis4)) 
223         
224             Debug.Log("用press按下了 “Axis4” “ ”"); 
225         
226   
227   
228         //ATouchpad键 圆盘交互 
229         //触摸触发 
230         if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad)) 
231         {    
232             Debug.Log("按下了 “Touchpad” “ ”"); 
233               
234             //方法返回一个坐标 接触圆盘位置 
235             Vector2 cc = device.GetAxis(); 
236             Debug.Log(cc); 
237             // 例子:圆盘分成上下左右 
238             float jiaodu = VectorAngle(new Vector2(1, 0), cc); 
239             Debug.Log(jiaodu); 
240             //下 
241             if (jiaodu > 45 && jiaodu < 135) 
242             
243                 Debug.Log("下"); 
244             
245             //上 
246             if (jiaodu < -45 && jiaodu > -135) 
247             
248                 Debug.Log("上"); 
249             
250             //左 
251             if ((jiaodu < 180 && jiaodu > 135) || (jiaodu < -135 && jiaodu > -180)) 
252             
253                 Debug.Log("左"); 
254             
255             //右 
256             if ((jiaodu > 0 && jiaodu < 45) || (jiaodu > -45 && jiaodu < 0)) 
257             
258                 Debug.Log("右"); 
259             
260         
261         //按动触发 
262         if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad)) 
263         
264             Debug.Log("用press按下了 “Touchpad” “ ”"); 
265         
266   
267          
268   
269   
270   
271     
272         // Update is called once per frame 
273         void Update () { 
274       
275     
276     //方向圆盘最好配合这个使用 圆盘的.GetAxis()会检测返回一个二位向量,可用角度划分圆盘按键数量 
277     //这个函数输入两个二维向量会返回一个夹角 180 到 -180 
278     float VectorAngle(Vector2 from, Vector2 to) 
279     
280         float angle; 
281         Vector3 cross = Vector3.Cross(from, to); 
282         angle = Vector2.Angle(from, to); 
283         return cross.z > 0 ? -angle : angle; 
284     
285 }  </pre></steamvr_trackedobject>
附上 vive手柄 3ds max模型下载:

下载地址:

http://www.52vr.com/forum.php?mod=viewthread&tid=30301