WeChat ID Gad-GameDev Intro 专业的游戏人社区(GAD.QQ.COM):为游戏开发者提供学习指导、问题解决、队员招募、游戏孵化等服务。免费组件下载、专业知识学习、组队游戏制作、项目孵化渠道。 在Zion插件中,也对其做了细分,如下面的UML类图,所有手柄的基类都是ZionControllerBase,而可追踪的手柄,则继承自它,ZionTrackedControllerBase为所有可追踪手柄的基类,它与其他手柄派生类的主要区别是,要提供速度和角速度的接口。 一、按键映射 无论是否可以追踪,手柄类最重要的实现是获取按键的状态,由于各平台的手柄,按键都有不同,底层返回的掩码与虚拟按键的映射也有不同,因此在兼容的时候我们需要先把这些映射,转换为我们自己定义的按键映射,再进行状态的判断。 映射关系 控制器返回的按键状态是通过一个64位整型返回的,每一位表示某个按键的状态。因此在各平台手柄类中,都有各按键对应的掩码变量,如SteamVR平台,按键掩码以ulong常量枚举。 如下表列出的,按键对应的位数(从右往左数)。 那么假设底层返回的按键状态码为000…000101(),用它与各按键对应的掩码进行&运算,如果得到的不是0(即有一位匹配),就能得到响应按键的状态,例如与System(000…000001)进行&运算,最后一位匹配,说明System键当前是Press状态。 因此,获取按键状态的接口就可以这样写,state.ulButtonPressed是底层返回的状态码,buttonMask是我们想知道的按键的掩码。 既然各平台都有上述的按键映射关系,但是我们不可能在自己的插件里为所有设备的按键都一一进行这样的映射。我们只会针对特定功能,做一个广泛的集合: 那么我们就需要做一次映射的转换,将平台底层状态码与其掩码比对后,转换为我们需要的兼容版本的的状态码。以实现类ZionTrackedControllerSteamVR为例: 接下来,将真实按键比对的结果转换为我们自定义的状态码。 可以看到,state.ulButtonPressed & Button.Enter是利用SteamVR平台的掩码和底层返回结果进行比对,如果比对成功,那么就给我们自己的状态码ulButtonPressed相应的位上置1,具体是哪个位,就要看后面的Zion.ZionController.Button.Enter,在Zion插件里,Enter键是“10”,那么此时状态码ulButtonPressed的右数第二位就置为1。然后利用这个转换后的状态码,在上层我们获取按键状态时,用自定义的状态码和自定义的按键掩码对比即可。 经过这样的转换,就可以实现,定义一套按键映射,匹配各平台的按键关系。 二、手柄基类:ZionControllerBase ZionControllerBase是所有支持手柄的基类,它提供了接口,获取按键状态以及轴数据,它的派生类需要实现各自的按键映射,返回状态码;以及实现自己的震动功能。 字段 ulButtonPressed:当前按键状态码 ulButtonPressedPrev:上一帧按键状态码 ulButtonTouched:当前触摸状态码 ulButtonTouchedPrev:上一帧触摸状态码 vAxes:轴数据数组 ulValidAxes:轴数据状态码 构造方法 ZionControllerBase () 可供重写的虛方法 Update(ref ulong ulButtonPressed, ref ulong ulButtonTouched, ref Vector2[] vAxes, ref ulong ulValidAxes) 需要各平台根据自己的特性进行重写,进行转换后,返回按键、触摸板的状态码,以及所有轴数据。 Vibrate(ZionController.Button button, uint duration, float frequency, float amplitude) 需要各平台根据自己的特性进行重写,震动手柄,不同平台对震动参数要求不一样,不关注的参数可以忽略。 Update() 不是Unity的Monobehaviour方法。最终在Monobehaviour类,ZionRender.cs的Update()中调用。 将这旧的按键状态码,触摸板状态码保存在xxxPrev参数中,重新获取新的状态码和轴数据。 按键回调方法 Notify(ButtonDownHandler buttonDown, ButtonUpHandler buttonUp,TouchDownHandler touchDown, TouchUpHandler touchUp, AxisDataHandler axisData) 普通手柄按键回调,轮询所有已定义的按键及轴数据状态,发送对应事件。 Notify(ZionController.Index index, TrackedButtonDownHandler buttonDown, TrackedButtonUpHandler buttonUp,TrackedTouchDownHandler touchDown, TrackedTouchUpHandler touchUp, TrackedAxisDataHandler axisData) 跟踪手柄按键回调,轮询所有已定义的按键及轴数据状态,发送对应事件。 实例方法 GetButton(ZionController.Button id):获取按键持续按下状态 GetButtonDown(ZionController.Button id):获取按键首次按下 状态 GetButtonUp(ZionController.Button id):获取按键松开状态 GetTouch(ZionController.Button id):获取按键持续触摸状态 GetTouchDown(ZionController.Button id):获取按键首次触摸状态 GetTouchUp(ZionController.Button id):获取按键离开触摸状态 GetAxis(ZionController.Button id, ref Vector2 axis):获取轴数据 三、跟踪手柄类 派生自手柄基类ZionControllerBase,但是由于跟踪手柄是红外线定位,所以提供接口,获取速度与角速度。 字段 velocity:手柄的速度 angularVelocity:手柄的角速度 上述参数都由派生类赋值 构造方法 ZionTrackedControllerBase () 可供重写的虛方法 SetIndex(ulong index) 更新手柄索引,派生类需要根据具体平台的实现处理左右手柄,将Zion的索引转换为自己平台的索引 GetVelocity() 获取速度,即字段velocity的值。 GetAngularVelocity() 获取角速度,即字段angularVelocity的值 HTC Vive手柄的跟踪手柄实现类。 字段 index:手柄索引 pose:位姿,用于获取速度和角速度 构造方法 ZionTrackedControllerSteamVR () 重写方法 SetIndex(ulong index) 将Zion插件里的索引转换为SteamVR平台的索引。 更新按键、触摸板、轴设备的状态及轴数据。其中三个ulong类型参数,都要经过上面说的按键映射转换。 更新速度、角速度。 获取上述参数,需要从底层取两个东西,按键状态和位姿:1、VRControllerState_t state;2.TrackedDevicePose_t pose 调用OpenVR来获取: 如此,得到axisid为-1的话就不必再继续,因为不是轴设备;如果不是-1,则调用OpenVR,传入轴设备索引,执行震动操作。 var system = OpenVR.System; if (system != null) { system.TriggerHapticPulse (index, (uint)axisid, (char)duration); } 嵌套类型 class Button{} SteamVR的按键掩码及映射 Oculus Touch手柄的实现类。 字段 controllerType:手柄类型(左/右),不同于SteamVR用index来区分手柄,Oculus Touch使用枚举类,因为它不止有左右之分,Oculus平台的手柄还支持Gamepad,Remote等。 preConnected:上一帧连接状态。 isConnected:当前连接状态。 buttonMap:button按键虚拟映射。 touchButtonMap:touchButton按键虚拟映射。 重写方法 SetIndex(ulong index) 将Zion插件里的索引转换为Oculus平台的OVRPlugin.Controller,手柄类型枚举。并初始化对应的按键虚拟映射(嵌套类构造方法传参)。 更新按键、触摸板、轴设备的状态及轴数据。其中三个ulong类型参数,都要经过上面说的按键映射转换。 更新手柄连接状态,发送Zion事件。 和SteamVR类似,也是从底层获取按键的状态state,但是这里要用自定义的方法将Thumbstick、Trigger、HandlerTrigger的轴数据值解析成键值,并填充到state.buttons。 上述嵌套类构造时需要传入手柄类型,按键映射会相应有改变。 《贪婪洞窟》谈贪婪设计丨腾讯GAD游戏创新大赛丨 游戏美术3D设计干货回顾丨为VR优化UE4渲染器丨 这么做设计才好玩丨Unity教程 MOBA类游戏核心设计分析 ...... 近期热文 Unity中的曲线绘制(二)——贝塞尔曲线 用C++搭建基本物品栏系统(附项目源代码) Author requires users to follow Official Account before leaving a comment Write a comment Write a comment Loading Most upvoted comments above Learn about writing a valuable comment Scan QR Code via WeChat to follow Official Account