从零开始丨使用Unity3D进行VIVE VR游戏开发(附项目源码)
SteamVR插件的导入
使用Unity3D进行VR游戏的开发,首先需要具备以下条件
1. 拥有一台显卡不低于GTX960性能的主机
2. 拥有一部VR设备,HTC Vive或者Oculus,因为只有连接上VR设备,Unity才能进行正常的调试(本文使用的是Vive设备)
3. 下载Valve的游戏平台Steam
4. 下载Unity3D插件商店中SteamVR插件
这几项缺一不可,没有VR设备的开发者,虽然能进行VR项目的开发,但是不能调试不能体验VR的效果,实际上是非常蛋疼的一件事。
另外吐槽一点,VR的调试需要带上VR设备,这个时候如果要动态的在项目中进行各种调试会非常的不方便。。。笔者尝试在VR设备中调出桌面进行操作也由于摇杆的操作比鼠标操作差很多而倍感不爽。。。所以没有VR设备的小伙伴们,赶快入手一个VR设备是正经,当然你也可以先通过学习如何开发来做一个前期的预热。
首先第一步,我们要做的是打开Steam,点击右上角的VR小标记来启动VR设备,第一次启动需要设置一下VR设备的房间环境,这点我就不多说了,不同的VR设备有不同的设置方式。最终能够识别出你的VR设备即可。本教程以HTC出的VIVE设备进行讲解。
SteamVR插件是全免费的,是Valve公司免费提供给大家的,这一点真是良心啊,如果有遇到无法下载或者下载非常慢的情况,本文最后将会提供插件的下载,有需要的同学请自行下载
截止本稿完成日期,最新版本为1.1.0,这个插件不大,只有几M,很实惠的插件哟。
好了,说了那么多,我们开始实战吧,首先创建一个新的Unity3D项目,然后导入我们的SteamVR插件。
在项目的根目录或者任意空白的地方点击右键,选择Import Package→Custom Package导入下载好的unity插件包(如果是从官网插件商店下载的,则会自动弹出导入窗口,不用这一步了)
导入所有的文件(如果是用旧版本更新,则更新所有的文件即可),点击Import
导入完成之后会弹出一个Unity项目设置的窗口,选择AcceptAll接受所有即可
你做了一个正确的选择~被表扬了~呜哈哈~~
导入完插件之后,可以在Scenes文件夹下找到一个演示的场景,example,建议有密集恐惧症的同学慎入。。。另外在Extras下也有两个小演示,一个是抛东西,一个是握东西,都是演示摇杆的使用方式这个我们后面再讲。
带上你的VR设备,运行这些场景就开始你的VR体验之旅了。
使用SteamVR插件预制开始VR的旅程
下面这一节将会教各位同学打造自己的VR场景,这一节是非常非常简单的,简单到我用一句话就能讲完,不信?我们来试试。
新建一个场景或者打开一个已有的场景,将SteamVR/Prefabs/[CameraRig]预制拖入场景。
然后。。。然后就完了,你可以运行这个场景,你的两个手柄都识别出来了,和你刚才看到官方的演示场景一样。
细心的同鞋一定发现了控制台一直在输出什么东西,不要担心,这是因为有场景中有两个AudioListener,我们把原来场景中主摄像机上的AudioListener移除掉即可
呵呵,这一步简单吧,然后我们开始进行下一步。
如何识别手势控制以及摇杆的各种操作
这一节将教会大家如何使用脚本来识别和控制VR设备
我们首先看一下刚刚拖到场景里的CameraRig预制
最外层的CameraRig这个预制就是你的VR设备在场景中的原点位置,挪动这个对象可以挪动整个VR在场景的位置,你的视角也会随之而移动。
Controller(left)和Controller(right)这个不用我多说了,这个是你的左右摇杆。有好学的同学要问了,摇杆上貌似没有区分左右的标记吧,怎么能区分哪个对象对应的是哪个摇杆呢?SteamVR默认会将第一个识别出来的摇杆作为right右摇杆,所以分左右主要看先后。最后的head不用说,就是各位同学的脑袋了,里面有两个对象,一个是作为渲染器的眼睛,一个是用来听声音的耳朵。
认识了这些东西之后,我们就开始编写一个小脚本,来识别一下他们。
在Main Camera上添加一个新的cs脚本,取名为StartVR
双击打开这个脚本
写入如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | using UnityEngine; using System.Collections; using Valve.VR; public class StartVR : MonoBehaviour { public SteamVR_TrackedObject leftHand; public SteamVR_TrackedObject rightHand; private VRControllerState_t leftControllerState; private VRControllerState_t rightControllerState; // Use this for initialization void Start () { } // Update is called once per frame void Update() { CVRSystem system = OpenVR.System; // 左手 if (system != null && system.GetControllerState(( uint )leftHand.index, ref leftControllerState)) { SteamVR_Controller.Device device = SteamVR_Controller.Input(( int )( uint )leftHand.index); float px = leftControllerState.rAxis0.x; float py = leftControllerState.rAxis0.y; if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger)) { Debug.Log( "按下trigger键" ); } else if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Trigger)) { Debug.Log( "按住trigger键" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) { Debug.Log( "抬起trigger键" ); } if (device.GetPressDown(EVRButtonId.k_EButton_ApplicationMenu)) { Debug.Log( "按下menu键" ); } else if (device.GetPress(EVRButtonId.k_EButton_ApplicationMenu)) { Debug.Log( "按住menu键" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_ApplicationMenu)) { Debug.Log( "抬起menu键" ); } if (device.GetTouchDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "触摸pad面板" ); } else if (device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "持续触摸pad面板" ); } else if (device.GetTouchUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "从pad面板上抬起手" ); } if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "按下pad按钮" ); } else if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "按住pad按钮" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "抬起pad按钮" ); } if (device.GetPressDown(EVRButtonId.k_EButton_Grip)) { Debug.Log( "按下Grip键" ); } else if (device.GetPress(EVRButtonId.k_EButton_Grip)) { Debug.Log( "按住Grip键" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_Grip)) { Debug.Log( "抬起Grip键" ); } if (device.GetHairTriggerDown()) { Debug.Log( "轻按trigger" ); } else if (device.GetHairTrigger()) { Debug.Log( "持续轻按trigger键" ); } else if (device.GetHairTriggerUp()) { Debug.Log( "抬起轻按trigger键" ); } } // 右手 if (system != null && system.GetControllerState(( uint )rightHand.index, ref rightControllerState)) { SteamVR_Controller.Device device = SteamVR_Controller.Input(( int )( uint )rightHand.index); float px = rightControllerState.rAxis0.x; float py = rightControllerState.rAxis0.y; if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger)) { Debug.Log( "按下trigger键" ); } else if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Trigger)) { Debug.Log( "按住trigger键" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) { Debug.Log( "抬起trigger键" ); } if (device.GetPressDown(EVRButtonId.k_EButton_ApplicationMenu)) { Debug.Log( "按下menu键" ); } else if (device.GetPress(EVRButtonId.k_EButton_ApplicationMenu)) { Debug.Log( "按住menu键" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_ApplicationMenu)) { Debug.Log( "抬起menu键" ); } if (device.GetTouchDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "触摸pad面板" ); } else if (device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "持续触摸pad面板" ); } else if (device.GetTouchUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "从pad面板上抬起手" ); } if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "按下pad按钮" ); } else if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "按住pad按钮" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) { Debug.Log( "抬起pad按钮" ); } if (device.GetPressDown(EVRButtonId.k_EButton_Grip)) { Debug.Log( "按下Grip键" ); } else if (device.GetPress(EVRButtonId.k_EButton_Grip)) { Debug.Log( "按住Grip键" ); } else if (device.GetPressUp(EVRButtonId.k_EButton_Grip)) { Debug.Log( "抬起Grip键" ); } if (device.GetHairTriggerDown()) { Debug.Log( "轻按trigger" ); } else if (device.GetHairTrigger()) { Debug.Log( "持续轻按trigger键" ); } else if (device.GetHairTriggerUp()) { Debug.Log( "抬起轻按trigger键" ); } } } } |
在场景中将VR的左右手对象拖到脚本相应参数的位置
然后不要带眼镜,直接运行程序,点击摇杆上的各个按键,控制台就能够输出各种打印信息了。
1. menu键
2. pad面板
3. 系统键
4. 指示灯
5. 充电口
6. 定位装置
7. trigger键
8. grip键
9.
使用脚本代码漫游3D场景
熟悉了以上流程,基本我们就可以开始制作VR游戏了,下面这一节将会教大家如何使用摇杆来控制视角在VR场景中漫游移动
首先修改代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | using UnityEngine; using System.Collections; using Valve.VR; public class StartVR : MonoBehaviour { public SteamVR_ControllerManager root; public SteamVR_GameView head; public SteamVR_TrackedObject leftHand; public SteamVR_TrackedObject rightHand; private VRControllerState_t leftControllerState; private VRControllerState_t rightControllerState; // Use this for initialization void Start () { } // Update is called once per frame void Update() { CVRSystem system = OpenVR.System; // 左手 if (system != null && system.GetControllerState(( uint )leftHand.index, ref leftControllerState)) { SteamVR_Controller.Device device = SteamVR_Controller.Input(( int )( uint )leftHand.index); float px = leftControllerState.rAxis0.x; float py = leftControllerState.rAxis0.y; if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad)) { OnPadButtonPressDown(px, py); } } // 右手 if (system != null && system.GetControllerState(( uint )rightHand.index, ref rightControllerState)) { SteamVR_Controller.Device device = SteamVR_Controller.Input(( int )( uint )rightHand.index); float px = rightControllerState.rAxis0.x; float py = rightControllerState.rAxis0.y; if (device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad)) { OnPadButtonPressDown(px, py); } } } public void OnPadButtonPressDown( float px, float py) { float area = 0.8f; float speed = 1f; if (px > 0f && py > -area && py < area) { // right root.gameObject.transform.position += head.gameObject.transform.right * speed; } if (px < 0f && py > -area && py < area) { // left root.gameObject.transform.position -= head.gameObject.transform.right * speed; } if (py > 0f && px > -area && px < area) { // up root.gameObject.transform.position += head.gameObject.transform.forward * speed; } if (py < 0f && px > -area && px < area) { // down root.gameObject.transform.position -= head.gameObject.transform.forward * speed; } } } |
然后将场景中VR设备的对象拖入相应位置
为了区分场景的位置,可以在空的场景中添加一些3D模型,或者你也可以打开以前做好的各种场景
接下来,戴上眼镜,运行程序,按下双手任意pad上的上下左右方向,就可以根据当前视角的前后左右进行移动了。这样我们的第一个VR程序就完成了,恭喜大家买入了VR开发的第一道门槛~