Unity Binding冲突解决探究

主要参考:

  • 官方文档:Unity官方Input System手册与API
  • 本文节选自:【Unity学习笔记】第十二 · New Input System 及其系统结构 和 源码浅析

可能存在冲突的几种情况:

  1. 同一Action下不同binding引用同一个control,且都非组合绑定
    在这里插入图片描述

    • button action:仅触发一次performed
    • value action:触发多次performed,有几个相同control就触发几次
    • passthrough:同value(不过注意按键释放值归0时passthrough也会触发performed)
  2. 不同Action下引用同相同control,且都非组合绑定
    在这里插入图片描述

    • 不存在冲突(不论什么action type),会触发各自Action的performed
  3. 同一Action下不同binding引用同不同control
    在这里插入图片描述

    • button:仅触发一次performed
    • value:例如绑定了JKL,按下J不放时触发一次perforemed;继续按下KL不放,不触发;然后依次释放JK,则又会触发两次performed;最后释放L不触发performed。
    • passthrough:比如绑定JKL,每个键的按压释放都会触发一次performed。

    说明: 这种情况和组合绑定情况有些类似,比如jkl,(j,k,l)的任何组合都认定为不同值,都会触发value或passthrough的值变更触发performed(jkl变成全0时不触发value类型的performed,但passthrough依旧会)。

    但是对于value来说,似乎跟binding在Action中的顺序有关,比如上面jkl绑定,如果按lkj顺序释放是不触发performed的,就比较奇怪。

  4. 不同Action下引用同一个control,且binding复杂度不同
    在这里插入图片描述

    • 两action都设为value、button:
      • 单按space键,触发fireCube;
      • 按ctrl+space,触发fireSphere;overrideModifiedFirst=true时,space+ctrl也触发fireSphere。
    • 也就是触发了高复杂度的Action,低复杂度action不再触发,这对组合绑定的冲突都同样使用。
    • 不考虑passthrough的情况,否则结果无预期效果。
  5. 同一Action下不同binding引用同一个control,且冲突的binding复杂度不同
    在这里插入图片描述

    • 按ctrl+space只会触发一次fireSphere
    • 按space会触发一次fireSphere
    • 对于overrideModifiedFirst=true,按space不放后会触发一次fireSphere,但此时再按ctrl,不会再触发fireSphere
  6. 上面4和5的结合
    在这里插入图片描述

    • 只按space,fireCube和fireSphere都会触发一次,这满足上面2和5的结论
    • 但按ctrl+space, fireCube和fireSphere也都会触发一次,这与4的结论不符合。因为从4、5情况的冲突解决想法,如果有高复杂度的绑定被消费了,冲突的低复杂度绑定就不再消费了,所以6这种案例可能是未曾考虑的边界情况,或许是bug。

总结:
总之,不考虑上面 第6点 这种特列,当存在冲突,优先高复杂度binding触发action,其所包含的冲突control就不同时触发其他action了。

而非组合绑定时,action下绑定多个相同control的binding,是允许同时触发多次action的。不同Action下引用同相同control,也允许同时触发两个action的。这两种不属于触发冲突,是由用户来控制的。
在这里插入图片描述

而对于同一Action下不同binding引用同不同control,官方文档举了个例子,如同时绑定手柄的左右扳机键,同时扣动时,会进行消除歧义的操作:当动作尚未启动时,它将对具有非默认值的第一个输入做出反应。一旦接收到这样的输入,它将开始跟踪该输入的来源。在动作正在进行时,如果接收到来自当前正在跟踪的控件以外的输入,它将检查输入是否具有比当前正在跟踪的控件更大的幅度。如果是这样,动作将从当前控件切换到具有更强输入的控件。

而如果当前control存在冲突且非"最激活"的,就会略过defaultInteraction处理,所以对于上面 第3点,依次按下jkl后,如果先释放kl是不会触发action的,只有先释放j才会触发action,但之后哪个control能拿到"最激活"的control,似乎和action上binding的顺序有关。
在这里插入图片描述
考虑到源码中处理controlStateChange的代码比较乱,而且modified 组合绑定曾出现过大bug,目前还不能相信官方对于按键冲突的处理没有问题,所以在使用Action绑定时,尽量避免冲突的发生。