Gear VR 入门教程之二 获取用户输入

来源:互联网 发布:dnf一进去网络连接中断 编辑:程序博客网 时间:2024/06/05 19:40
首先简单介绍下Gear  VR头盔上的功能按键:
     Gear VR 第一代 的功能按键全部位于头盔右侧,分别如下:
  • 两个音量增减键,用来调节手机的音量,功能和手机本身的音量键完全一样
  • 一个返回键,类似android手机上的返回键,在VR游戏中可以用来实现,返回主菜单,或者退出游戏之类的操作
  • 触控区域,可以通过该区域识别玩家的点击,按下,松开,双击,长按,以及滑动操作,这将是玩家在游戏内的主要操作方式(还有一个就是头部的转动)。当然从个人体验来讲,因为该区域位于头部侧方,不同于手机屏幕,不适合让玩家通过滑动来完成太复杂的操作,超过上下左右四方向以外的滑动识别,体验都不是很好。
  •     
  • 通过图片和按键讲解可以看到,gearVR 与暴风魔镜之流的设备的区别就是,它通过USB口连接手机,然后玩家可以通过头戴设备的输入完成一些相对完善的操作。
Unity是如何映射这些功能按键的:
  •      用Unity创建一个空项目,GearVRTest_1_2,然后打开InputManager:通过Edit-> Project Settings ->Input
  • 点开第一个Fire1:可以看到这个名称对应的按键是Left Ctrl(键盘上的左Ctrl键),以及mouse 0(鼠标左键,同时也是触屏手机的单点触屏操作,也是GearVR touchpad的点击操作) 
  • 点开第二个Fire1:可以看到对应的是joystick button 0 (也就是手柄上第二排第一个按键)
  • 点开唯一的一个Cancel:可以看到对应的是escape(键盘左上角的esc键和安卓手机和GearVR的返回键),以及joystick button 1(手柄上的第二个按键)
  • 通过这些按键映射可以看到,我们可以通过合理的按键映射,可以使我们的VR游戏做到手机,头显和蓝牙手柄公用一套按键逻辑(VR头显bing)
通过代码获取玩家操作:
  •      我们要实现的是一个获取玩家输入的脚本,而不处理具体逻辑,行为逻辑代码通过委托的方式从该脚本获取玩家的操作
  • using UnityEngine;using System.Collections;using System;namespace com.bt.gearVR{    public class VRInput : MonoBehaviour    {        public enum SwipeDirection        {            NONE,            UP,            DOWN,            LEFT,            RIGHT,        };        public event Action<SwipeDirection> OnSwipe; //在touchPad上滑动        public event Action OnClick; //点击touchPad        public event Action OnDown; //按下        public event Action OnUp;//抬起        public event Action OnDoubleClick;//双击        public event Action OnCancel;//点击touchPad的返回键        [SerializeField] private float m_DoubleClickTime=0.3f;//有效双击的最大时间间隔        [SerializeField] private float m_SwipeWidth=0.3f; //有效滑动的最小位移        private Vector2 m_MouseDownPosition; //记录手指按下的位置        private Vector2 m_MouseUpPosition; //记录手指抬起的位置        private float m_LastMouseUpTime; //上一次手指抬起的时间,用来检测双击        private float m_LastHorizontalValue;         private float m_LastVerticalValue;                public float DoubleClickTime { get { return m_DoubleClickTime; } }        // Use this for initialization        void Start()        {        }        // Update is called once per frame        private void Update()        {            CheckInput();        }        private void CheckInput()        {            SwipeDirection swipe = SwipeDirection.NONE;            if(Input.GetButtonDown("Fire1"))//手指触碰到touchPad            {                m_MouseDownPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);                if(OnDown!=null)                {                    OnDown();                }            }            if(Input.GetButtonUp("Fire1"))//手指离开touchPad            {                m_MouseUpPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);                swipe = DetectSwipe();//            }            if(swipe==SwipeDirection.NONE)            {                swipe = DetectKeyboardEmulatedSwipe();            }            if(OnSwipe!=null)            {                OnSwipe(swipe);            }            if(Input.GetButtonUp("Fire1"))            {                if(OnUp!=null)                {                    OnUp();                }                if(Time.time-m_LastMouseUpTime<m_DoubleClickTime)                {                    if(OnDoubleClick!=null)                    {                        OnDoubleClick();                    }                }                else                {                    if(OnClick!=null)                    {                        OnClick();                    }                }                m_LastMouseUpTime = Time.time;            }            if(Input.GetButtonDown("Cancel")) //点击头显上的返回键            {                if(OnCancel!=null)                {                    OnCancel();                }            }        }        /// <summary>        /// 检测滑动方向        /// </summary>        /// <returns> 滑动方向,上下左右</returns>        private SwipeDirection DetectSwipe()        {            Vector2 swipeData = (m_MouseUpPosition - m_MouseDownPosition).normalized;            bool swipeIsVertical = Mathf.Abs(swipeData.x) < m_SwipeWidth;            bool swipeIsHorizontal = Mathf.Abs(swipeData.y) < m_SwipeWidth;            if(swipeData.y>0f && swipeIsVertical)            {                return SwipeDirection.UP;            }            if(swipeData.y<0 && swipeIsVertical)            {                return SwipeDirection.DOWN;            }            if(swipeData.x>0 && swipeIsHorizontal)            {                return SwipeDirection.RIGHT;            }            if(swipeData.x<0&& swipeIsHorizontal)            {                return SwipeDirection.LEFT;            }            return SwipeDirection.NONE;        }        //检测键盘或者手柄模拟的晃动方向        private SwipeDirection DetectKeyboardEmulatedSwipe()        {            float horizontal = Input.GetAxis("Horizontal");            float vertical = Input.GetAxis("Vertical");            bool noHorizontalInputPreviously = Mathf.Abs(m_LastHorizontalValue) < float.Epsilon;            bool noVerticalInputPreviously = Mathf.Abs(m_LastVerticalValue) < float.Epsilon;            m_LastHorizontalValue = horizontal;            m_LastVerticalValue = vertical;            if (vertical > 0f && noVerticalInputPreviously)                return SwipeDirection.UP;            if (vertical < 0f && noVerticalInputPreviously)                return SwipeDirection.DOWN;            if (horizontal > 0f && noHorizontalInputPreviously)                return SwipeDirection.RIGHT;            if (horizontal < 0f && noHorizontalInputPreviously)                return SwipeDirection.LEFT;            return SwipeDirection.NONE;        }        private void OnDestroy()        {            OnSwipe = null;            OnClick = null;            OnDoubleClick = null;            OnDown = null;            OnUp = null;        }    }}
    然后是测试代码,后面会上传项目路径,会有一个控制玩家移动的脚本,这里不再贴出
  • using UnityEngine;using System.Collections;namespace com.bt.gearVR{    public class VRInputTest : MonoBehaviour    {        [SerializeField] private VRInput m_VRInput;        //该脚本激活时,注册对玩家操作的监听        void OnEnable()        {            m_VRInput.OnCancel += OnCalcel;            m_VRInput.OnClick += OnClick;            m_VRInput.OnDown += OnDown;            m_VRInput.OnUp += OnUp;            m_VRInput.OnDoubleClick += OnDoubleClick;            m_VRInput.OnSwipe += OnSwip;        }                void OnSwip(VRInput.SwipeDirection swipeDirection)        {            if(swipeDirection!=VRInput.SwipeDirection.NONE)            {                Debug.Log("Unity+OnSwipe" + swipeDirection);            }                   }        //取消对玩家输入的监听        void OnDisable()        {            m_VRInput.OnCancel -= OnCalcel;            m_VRInput.OnClick -= OnClick;            m_VRInput.OnDown -= OnDown;            m_VRInput.OnUp -= OnUp;            m_VRInput.OnDoubleClick -= OnDoubleClick;            m_VRInput.OnSwipe -= OnSwip;        }        void OnCalcel()        {            Debug.Log("Unity+OnCancel");        }        void OnClick()        {            Debug.Log("Unity+OnClick");        }        void OnDown()        {            Debug.Log("Unity+OnDown");        }        void OnUp()        {            Debug.Log("Unity+OnUp");        }        void OnDoubleClick()        {            Debug.Log("Unity+OnDoubleClick");        }        // Use this for initialization        void Start()        {        }    }}

  • 注1:GearVR第二代又新加了一个Home键,功能类似于手机上的Home键,游戏内用不到这里不再列出
  • 注2:玩家在游戏内移动时,不可以直接移动摄像机本身,因为GearVR限制了摄像机的移动,但是可以把摄像机挂到一个父节点下,通过移动父节点来移动摄像机
  • 注3:本教程中的部分代码和图片来源于Unity官方的教程,VRSamples,感兴趣的读者可以去AssetsStore下载
  • Demo下载地址:https://git.coding.net/bt_coder/GearVRTurorial_1_2.git

0 0