7.5.4 追踪光标的实现
上面小节介绍了使用UGUI在场景中开发的主菜单以及侧面返回菜单,为了提示用户在头部姿态发生变化时双眼中间位置注视在什么地方,以便于更好地拾取菜单按钮,使用追踪光标来实时更新并指示眼睛注视的位置,具体代码如下。
代码位置:见随书源代码/第7章/GearVR_Demo/Assets/Scripts目录下的GazePointer.cs。
1 public override void Process() { //该脚本继承自BaseInputModual类,该方法每一帧刷新 2 CastRayFromGaze(); //向注视方向发射线 3 UpdateCurrentObject(); //更新当前拾取到的对象 4 PlaceCursor(); //将光标移至注视位置 5 HandlePendingClick(); //处理单击期间事件 6 HandleTrigger();} //处理触发事件 7 private void CastRayFromGaze() { 8 if (pointerData == null) { //指针数据若为空 9 pointerData = new PointerEventData(eventSystem);} //实例化指针事件数据对象 10 pointerData.Reset(); //重新设置事件到默认状态 11 pointerData.position = new Vector2(hotspot.x * Screen.width, hotspot.y * Screen.height); //当前指针位置 12 eventSystem.RaycastAll(pointerData, m_RaycastResultCache); //使用所有配置好的RayCasters发射线 13 pointerData.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache); //当前射线返回结果 14 m_RaycastResultCache.Clear();} 15 private void UpdateCurrentObject() { 16 var go = pointerData.pointerCurrentRaycast.gameObject; //获取当前射线拾取到的对象 17 HandlePointerExitAndEnter(pointerData, go); //处理指针离开和进入事件 18 var selected = ExecuteEvents.GetEventHandler<ISelectHandler>(go); 19 if (selected == eventSystem.currentSelectedGameObject) { 20 ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, GetBaseEventData(), 21 ExecuteEvents.updateSelectedHandler);} //执行对象上的事件 22 else { 23 eventSystem.SetSelectedGameObject(null, pointerData);}} //设置该对象为被选中对象 24 private void PlaceCursor() { 25 if (cursor == null) //判断光标是否为空 26 return; 27 var go = pointerData.pointerCurrentRaycast.gameObject; //获取当前拾取到的对象 28 if(go==null){ 29 return;} 30 Constraints.RayCasterObjName = go.name; //记录下当前获取对象的名称,方便索引 31 cursor.SetActive(go != null); //拾取对象为空就将光标设置为未激活状态 32 if (cursor.activeInHierarchy) { //如果光标处在激活状态 33 Camera cam = pointerData.enterEventCamera; //获取发射线的相机引用 34 float dist = pointerData.pointerCurrentRaycast.distance + cam.nearClipPlane; //计算相机距拾取点距离 35 cursor.transform.position = cam.transform.position + cam.transform.forward * dist;}} //设置光标位置 |
第1~6行为重写基类BaseInputModual的每一帧刷新方法Process,该方法中调用了用于实现确定光标位置以及失去对象的重要方法,这也是对于UI事件系统的高级应用,需要对EventSystem、PointerEventData、BaseInputModual以及BaseRayCaster类详细了解。
第7~23行为CastRayFromGaze和UpdateCurrentObject方法的代码实现,前者用于使用场景中相机发射射线并返回结果存储在pointerEventData(PointerEventData类型)中,后者用于实时更新射线拾取到的当前对象。
第24~35行为PlaceCursor方法的代码实现,该方法用于设置光标位置,使其随相机发射射线方向的改变而不断改变位置,能够辅助用户清楚目前正在注视的点,以便更好地对目标进行拾取操作等。
7.5.5 触摸板事件监听
该案例当中用于触发事件的外部输入方式是侧面触摸板,在满足某种特定的条件时单击侧面触摸板,会触发相应的事件,比如OVRPlayerController左右旋转、发射"炮弹"击打Box和Cylinder等。对Oculus Mobile SDK中的OVRTouch.cs脚本稍作改动就可以实现相应功能,具体代码如下。
代码位置:见随书源代码/第7章/GearVR_Demo/Assets/OVR/Moonlight/Scripts目录下的OVRTouchpad.cs。
1 public sealed class OVRTouchpadHelper : MonoBehaviour{ 2 private GameObject ObjShooting; //炮弹预制体引用 3 private Transform ObjShootingPos; //实例化子弹初始位置 4 private bool IsShooting=false; //是否发射炮弹 5 void Awake(){ 6 UnityEngine.Object go = Resources.Load ("Sphere",typeof(GameObject)); //获取炮弹预制体 7 ObjShooting = go as GameObject; //转换成游戏对象 8 ObjShootingPos = GameObject.Find ("CenterEyeAnchor").transform; //获取CenterEyeAnchor位置 9 DontDestroyOnLoad(gameObject);} //加载时不删除该对象 10 void Start(){ 11 OVRTouchpad.TouchHandler += LocalTouchEventCallback;} //将触摸事件监听回调方法加入事件列表 12 void Update(){ 13 OVRTouchpad.Update();} //更新OVRTouchpad 14 public void OnDisable(){ 15 OVRTouchpad.OnDisable();} 16 void LocalTouchEventCallback(object sender, EventArgs args){ //触摸事件监听方法 17 var touchArgs = (OVRTouchpad.TouchArgs)args; //强制类型转换:基类-继承类 18 OVRTouchpad.TouchEvent touchEvent = touchArgs.TouchType; //获取触摸事件 19 switch(touchEvent){ 20 case OVRTouchpad.TouchEvent.SingleTap: //单击事件 21 Debug.Log("SINGLE CLICK\n");{ //打印调试信息 22 if(Constraints.IsRaycaster_Right==true){ //当射线离开"右转菜单",此变量置为false 23 Constraints.RotateToRight=true; //当转向完成此变量置为false} 24 if(Constraints.IsRaycaster_Left==true){ //当射线离开"左转菜单",此变量置为false 25 Constraints.RotateToLeft=true;} //当转向完成此变量置为false 26 if(Constraints.IsRayCaster_BoxBack==true){ //当射线离开Box返回图片时置为false 27 Constraints.RotateToLeft=true;} //当转向完成此变量置为false 28 if(Constraints.IsRayCaster_CylinderBack==true){ //当射线离开Cylinder返回图片时置为false 29 Constraints.RotateToRight=true;} //当转向完成此变量置为false 30 if(Constraints.Shooting==true&&Constraints.IsRaycaster_Right==false //左转变量为false 31 &&Constraints.IsRaycaster_Left==false&&Constraints.IsRayCaster_BoxBack==false&& 32 Constraints.IsRayCaster_CylinderBack==false){ //左转变量为false,Box和Cylinder返回变量为false 33 Shooting();}} //发射"炮弹" 34 break; 35 case OVRTouchpad.TouchEvent.Left: //左滑事件 36 Debug.Log("LEFT SWIPE\n"); //打印调试信息 37 break; 38 case OVRTouchpad.TouchEvent.Right: //右滑事件 39 Debug.Log("RIGHT SWIPE\n"); //打印调试信息 40 break; 41 case OVRTouchpad.TouchEvent.Up: //上滑事件 42 Debug.Log("UP SWIPE\n"); //打印调试信息 43 break; 44 case OVRTouchpad.TouchEvent.Down: //下滑事件 45 Debug.Log("DOWN SWIPE\n"); //打印调试信息 46 break;}} 47 void Shooting(){ //发射炮弹方法 48 GameObject go = Instantiate(ObjShooting,new Vector3(ObjShootingPos.transform. position.x, 49 ObjShootingPos.transform.position.y,ObjShootingPos.transform.position.z), //初始化炮弹预制体 50 Quaternion.identity)as GameObject; 51 go.GetComponent<Rigidbody>().AddForce(ObjShootingPos.forward*2000);//向前发射 52 }} |
第1~15为获取炮弹预制体、炮弹初始化位置,以及在场景加载后在Assets/Resources文件夹中加载炮弹资源和在Start方法中添加触摸事件处理方法到事件列表中。其中在Update和OnDestory方法中调用的OVRTouchpad中的方法没有具体功能,可以注释。
第16~46行为LocalTouchEventCallback处理触摸事件的回调方法,其中包括SingleTap、Left、Right、Up以及Down 5个触摸事件,本案例中只用到了SingleTap单击触摸事件,单击侧面触摸板后根据具体条件不同分别会发生向右旋转、向左旋转、左返回主菜单、右返回主菜单和发射炮弹几种操作。
第47~52行为用于炮弹发射的方法,使用预制体根据CenterEyeAnchor的位置实例化炮弹,然后获取该物体的刚体组件,添加一个沿CenterEyeAnchor正方向的力,使其"炮弹"飞出去击打Box和Cylinder。
7.5.6 部署运行APK的步骤
上面小节讲解了虚拟现实场景的开发过程,从场景中打包的APK安装到手机上,将Gear VR头盔插上手机之后在Oculus Home找不到该应用,手机桌面也找不到图标,但实际上已经安装好了,接下来介绍如何将已经制作好的APK配合Gear VR头盔及手机运行出来,具体步骤如下。
(1)Gear VR应用或者游戏就是Android游戏或者应用,除了从三星手机上Oculus Home商店运行软件之外,还可以自己创建游戏及应用,因为根据设备ID绑定过签名文件,所以在Oculus Home中找不到已经安装的应用。
(2)通过下载并安装"ES文件浏览器"应用,可以运行提取版(免费/破解版)Gear VR游戏以及可以在三星手机上找到已经安装好的应用图标,如图7-40所示,ES文件浏览器下载地址:http://pan.baidu.com/s/1i5tXEFr。
(3)已经确保安装了Gear VR应用之后,在手机桌面打开"ES文件管理器",单击"应用"查找已经安装的应用,如图7-33所示。找到应用之后单击会弹出"属性"提示框,如图7-41所示,单击"打开"会提示"请插入Gear VR设备",如图7-42所示,这时将手机插入Gear VR头戴设备中并带上头盔即可。
7.6 本章小结
本章对Gear VR硬件以及Oculus Mobile SDK进行了详细介绍,尤其着重介绍了如何在Unity中使用Oculus提供的SDK开发移动平台的Gear VR应用。通过对本章内容的学习,相信读者能够系统全面地掌握Gear VR的开发过程,增强了在开发中解决实际问题的能力。
7.7 习题
1.简要介绍Gear VR的硬件组成。
2.下载Oculus Mobile SDK,并利用手机的ID在Oculus官网获取签名文件。
3.试述开发Gear VR项目的软硬件要求。
4.列举SDK中的脚本,并试述每个脚本的具体功能。
5.列举影响游戏性能的几个因素。
6.开发一个基于Gear VR SDK的简单案例。
本文选自《VR及AR开发高级教程—基于Unity》第七章,本站经人民邮电出版社和作者的授权。
版权声明:51Testing软件测试网获清华大学出版社和作者授权连载本书部分章节。任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。