Unity新输入方案InputSystem介绍-(二)

一、为什么重点讲InputAction?
其实Unity有不少预览包,总是会出现一种功能,有多种调用方式。InputSystem的官方例子(在InputSystem/Assets/Demo/SimpleDemo/文件夹下),也列举几种检测输入的例子。有一定代码能力的小伙伴,基本没什么压力。除了上一篇的直接查询设备状态外,个人觉得最突出的还是基于InputAction的全新输入事件系统。不仅提供全新的InputActionAsset,而且整个方案中,大部分可供开发者编辑的要素还是InputAction。


二、怎么编辑InputAction?
让我们打开一个InputActionAsset文件,如Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/DefaultInputActions.inputactions。这里会接触几个新名词,如InputActionMap(InputAction的集合)、InputControlScheme(用于筛选InputControl)、InputBinding(用于绑定InputAction和InputControl)等。

①管理InputControlScheme和用InputControlScheme筛选InputControl;
②筛选输入设备;
③InputActionMap的编辑列表;
④选中的InputActionMap对应的InputAction编辑列表;
⑤选中的InputAction或InputBinding的编辑界面;
现在应该可以了解整套InputActionAsset的作用:保存多个InputActionMap(不同使用场景),InputActionMap用于检索InputAction(具体的行为),InputAction用于表示该行为由什么InputControl(输入源)触发,InputBinding作为InputAction和InputControl连接的桥梁,InputControlScheme用于筛选InputControl。
目前我发现代码引用InputAction的方式有三种:
1.声明InputAction字段,然后在Inspector面板上编辑;
2.声明InputActionReference字段,然后选择InputActionAsset文件的子资源InputActionReference;

3.直接代码创建InputAction,也是之前说的强大的字符串反序列化功能;
public InputAction(string name = null, string binding = null, string interactions = null, string processors = null, string expectedControlLayout = null);
第一种和第二种比较适合开发者编辑,而且无论是你在代码声明InputAction,还是在InputActionAsset→InputActionMap新建一个InputAction,操作都是一样的。
1.选择InputAction,按下+按键,选择你要添加的绑定类型(简单、一轴混合,二轴混合):

2.选择新建的InputBinding,在Binding→Path选择想要侦听的InputControl:

3.在Interactions添加InputAction触发模式,然后编辑Interaction(可选):


4.在Processors添加InputAction返回值的修饰操作,然后编辑Processor(可选):


5.最后得到一个关于开火的InputAction,同时一个InputBinding可以有零个或多个Interaction和Processor。想增加更多InputBinding,重复1~4步骤即可:


三、怎么使用InputAction?
我们已经可以自己创建和获取InputAction了,那么具体怎么用呢?其实InputAction有三个事件回调步骤,分别为started(开始)、performed(执行)、canceled(取消),需要查阅文档来了解不同Interaction的回调情况。我这边以刚才编辑的InputAction为例:
1.新建一个MonoBehaviour脚本,获取InputAction,可以是从InputActionAsset查阅获取,直接引用,或手动创建;
2.在Start函数注册回调事件,并启用InputAction:
void Start(){
//...
if(inputAction!=null){
inputAction.performed+=OnPerformed;
inputAction.Enable();
}
}
3.在Destroy函数反注册回调函数,并禁用InputAction:
void OnDestory(){
//...
if(inputAction!=null){
inputAction.performed-=OnPerformed;
inputAction.Disable();
}
}
4.在回调函数处理Input事件:
void OnPerformed(InputAction.CallbackContext ctx){
if(ctx.ReadValue<float>()<0.25f) {
print("Fire is Released!!!");
}else {
print("Fire is Pressed!!!");
}
}
5.回到Unity编辑器,点击Play,看看是否运行成功:

可能有人注意到了,光是一个InputAction需要做的工作有点麻烦,使用多个InputAction不就累死。还记得上一篇说到的InputActionAsset的自动生成C#类,就是帮你生成一个帮助类。它帮你注册和反注册的工作都做了,而且还声明一个接口,让你实现对不同InputAction的处理。



四、一些题外话
由于本人上一家公司的主业还是研发XR设备的,所以本系列文章有点XR设备怎么怎么着。如果Unity在2015年就推出InputSystem的正式版,我想我那家公司的SDK的开发人员会减少一半以上,而且我也能少受罪。其实我连UE4的输入SDK都搞过,但整体的开发体验不是很好。SteamVR虽说是一个很好VR设备兼容方案,但是它不支持安卓端(如一体机)。而Unity的InputSystem简直不能再好用了,原生库上封装一个Layout,完事。
目前XR设备研发,还是处于低潮期,所以我可能不会讲第三方硬件接入InputSystem。而且如果有熟读C#能力的话,其实就是照着葫芦画瓢。现在大部分大厂都已经在渲染端和Unity完成整合(之后可以用LWRP),而厂家的SDK都是提供一些输入接口和工具库。等InputSystem推出正式版,除了一些特殊功能外,那基本没有厂家的SDK什么事了。
但是不管XR发展如何,我觉得还是要把一些积累的开发经验分享出来。毕竟如果一声不吭就跑去卖炒面,那么有愧于那些还在XR开发中打滚的老铁们。虽然到了现在还是想吐槽老东家,但毕竟也受到其不少照顾,做人要厚道。虽然因为正式版未发表(还有我懒),只讲了皮毛,但希望这些文章能给那些被输入SDK折磨的Unity开发者一些帮助。下一篇就是外传,分享如何开发多平台VR的经验了。YouSing,我们走(喂~感觉哪里不对劲)。