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

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/u013746357/article/details/52416481
首先简单介绍下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

猜你喜欢

转载自blog.csdn.net/u013746357/article/details/52416481
今日推荐