更新说明下:今天我发现本文中设计的代码有些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,欢迎测试!