暴风魔镜安卓手柄输入检测接口
更新说明下:今天我发现本文中设计的代码有些bug,关于按下和抬起状态的检测只能监听一次,关于解决方案,我会尽快补上,谢谢。
使用暴风魔镜做安卓VR开发,自己尝试弄了一天,发现效果太差,主要是手柄输入函数检测不到,或者检测的不灵敏。第二天才想起来百度,然后才发现暴风魔镜官方已经提供了手柄SDK。链接地址http://bbs.open.mojing.cn/forum.php?mod=viewthread&tid=48&extra=page%3D1。
好,以上就是原生的SDK,关于相机我就不说了,最要紧是把手柄函数给找到。开发文档大概介绍了一下,在BaoFengZeemoteManager.cs中提供了按键的获取事件,能够获取到键按下和按键抬起的事件。
经过测试,阿亮发现了以下缺点:
1,提供的方法不好用,或者说根本没有像Input输入检测那样的函数:没有实际意义的按下,一直按,抬起的直接获取函数
2,不能同时多个按键的检测(例如只能单方向行走,走的时候不能开火等)
3,抬起键的检测不好,例如同时按下了多个键,只能检测其中一个是否抬起
其他的不说,基本的按键事件不能正常使用,这个函数无异于鸡肋。OK,既然原开发者不走心,那咱就走点心吧。
首先,要明确需求,就是为了解决上面提到的三个问题。
在解决这个问题之前,先来看看BaoFengZeemoteManager.cs是怎么跑起来的,ZeemoteManager.cs是获取事件的,然后把事件处理的结果传递个BaoFengZeemoteManager.cs,它主要有两个函数,一个是获取按下事件,另一个是抬起事件。
public void ZeemoteUpBtn(string currentButton)//抬起的按键名称 { state = "Button up: " + currentButton; //Message = currentButton; switch (currentButton) { case "OK": break; case "BACK": break; case "MENU": break; case "LEFT_BUTTON": break; case "RIGHT_BUTTON": break; case "UP_BUTTON": break; case "DOWN_BUTTON": break; case "CENTER_POSITION": break; case "A": break; case "B": break; case "C": break; case "D": break; }
}
public void ZeemoteDownBtn(string currentBtn)//按下的按键名称 { state = "Button down: " + currentBtn; switch (currentBtn) { case "OK": break; case "BACK": break; case "MENU": break; case "LEFT_BUTTON": break; case "RIGHT_BUTTON": break; case "UP_BUTTON": break; case "DOWN_BUTTON": break; case "CENTER_POSITION": break; //以下为老遥控器(一代遥控器)特有按键; case "A": break; case "B": break; case "C": break; case "D": break; }
}
OK,拿到这两个函数怎么用呢,直接用很难用,你总不能把输入逻辑的处理放到这里面来吧?还有,像Input.GetButton(name),Input.GetButtonDown(name),Input.GetButtonUp(name)的检测输入性函数也是没有的,如何丰富这个鸡肋呢?
算法这东西需要你分析逻辑关系的,我们来看看如何处理这个逻辑:他们每次接收一个参数数值,同时更新掉上一个。针对同一个按键,这两个函数是互斥的。
根据这个条件,以及我们的需求,然后我想到了这个方案:一个按键有三个状态:按下,一直按,抬起。用一个hashtable将按键和状态存起来,执行ZeemoteDownBtn(string currentBtn)和ZeemoteUpBtn(string currentButton)时去调整状态。其他类调用检测输入时,去哈希表中去查它对应的状态就行了。
更改以上的两个函数如下:
public void ZeemoteUpBtn(string currentButton) { state = "Button up: " + currentButton; //Message = currentButton; switch (currentButton) { case "OK": break; case "BACK": break; case "MENU": break; case "LEFT_BUTTON": break; case "RIGHT_BUTTON": break; case "UP_BUTTON": break; case "DOWN_BUTTON": break; case "CENTER_POSITION": break; case "A": break; case "B": break; case "C": break; case "D": break; } SetAxis(currentButton,false);//调整按键的状态 } private void SetAxis(string buttonName,bool isPress) {//抬起键和按下,一直按的事件是互斥的 ((Hashtable)table[buttonName])["up"] = !isPress; ((Hashtable)table[buttonName])["down"] = isPress; ((Hashtable)table[buttonName])["press"] = isPress; } private Hashtable table = new Hashtable(); public void ZeemoteDownBtn(string currentBtn) { state = "Button down: " + currentBtn; switch (currentBtn) { case "OK": break; case "BACK": break; case "MENU": break; case "LEFT_BUTTON": break; case "RIGHT_BUTTON": break; case "UP_BUTTON": break; case "DOWN_BUTTON": break; case "CENTER_POSITION": break; //以下为老遥控器(一代遥控器)特有按键; case "A": break; case "B": break; case "C": break; case "D": break; } if ((bool)((Hashtable)table[currentBtn])["down"]==false) {//按下事件是一次性的,所以只有当down为false时再更新 SetAxis(currentBtn, true); } if (currentBtn == AndroidInput.CENTER_POSITION.ToString())//这个是轴归零时函数 { SetAxis(AndroidInput.LEFT_BUTTON.ToString(), false); SetAxis(AndroidInput.RIGHT_BUTTON.ToString(), false); SetAxis(AndroidInput.UP_BUTTON.ToString(), false); SetAxis(AndroidInput.DOWN_BUTTON.ToString(), false); } }
好,函数改好了,看看怎么用:
public bool GetButton(string button) {//一直按状态 return (bool)(((Hashtable)table[button])["down"]); } public bool GetButtonDown(string button)//按下的检测 { bool isPress = (bool)(((Hashtable)table[button])["press"]); if (isPress && (bool)(((Hashtable)table[button])["down"])) { ((Hashtable)table[button])["press"] = false;//检测过按下事件后,将其状态清零 return true; } return false; } public bool GetButtonUp(string button)//检测抬起按键事件 { bool isUp = (bool)(((Hashtable)table[button])["up"]); if (isUp) { ((Hashtable)table[button])["up"] = false;//检测过后清零 return true; } return false; }
修改完毕,手柄能用了!
例如,按下MENU键,直接调用:
BaoFengZeemoteManager.Instance.GetButtonDown(AndroidInput.MENU.ToString());
一直按:
BaoFengZeemoteManager.Instance.GetButton(AndroidInput.MENU.ToString());
抬起:
BaoFengZeemoteManager.Instance.GetButtonUp(AndroidInput.MENU.ToString())
结尾来谈一下第一人称控制器,不要说这个多简单,unity自带什么的,我知道,可是那是基于PC端有鼠标键盘的情况,怎样用手柄控制呢?
我为什么提出这个问题--相机。在PC端,用鼠标移动控制相机还有角色旋转,这是最简单不过了,可是,暴风魔镜的相机旋转是陀螺仪控制的,角色怎么跟着旋转呢?因为第一人称的MouseLook是通过计算鼠标的XY偏移量来确定角色的方位的,如果方位不正确,那么角色的移动就不会以相机的正前方为方向移动了。
我开始用相机的角度,来调整角色的旋转角度,但是问题又来了:相机是基于角色的,旋转角色,相机又跟着转,好吧,具体的问题,大家可以试试。
我解决了?那是当然。来看看图吧。
最后是一个演示demo的apk,有暴风魔镜的小伙伴们可以试试,Menu键切换武器。OK键发射。链接: http://pan.baidu.com/s/1hqhFKCO 密码: mf7q
原文链接http://www.cnblogs.com/jqg-aliang/p/4615029.html 转载请申明出处,谢谢!
游戏已更新:链接:http://pan.baidu.com/s/1dD8Q8RB 密码:adwf,欢迎测试!