InputSystem按键重绑定

参考教程

【unity小技巧】新输入系统InputSystem重新绑定控制按键(最全最完美解决方案)_unity input system-CSDN博客

action的binding索引

image-20250111140638150

一个action下存在多个binding的情况下,如果想要通过所以来获取到binding对象,以上是它们的索引,从0开始,依次递增

索引获取

在InputSystem官方给出的Samples中,可以通过预先设置的 binding 和代码来获取到指定binding的有效索引

属性定义

1
2
[SerializeField]
private string m_BindingId;

获取索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// <summary>
/// Return the action and binding index for the binding that is targeted by the component
/// according to
/// </summary>
/// <param name="action"></param>
/// <param name="bindingIndex"></param>
/// <returns></returns>
public bool ResolveActionAndBinding(out InputAction action, out int bindingIndex)
{
bindingIndex = -1;

action = m_Action?.action;
if (action == null)
return false;

if (string.IsNullOrEmpty(m_BindingId))
return false;

// Look up binding index.
var bindingId = new Guid(m_BindingId);
bindingIndex = action.bindings.IndexOf(x => x.id == bindingId);
if (bindingIndex == -1)
{
Debug.LogError($"Cannot find binding with ID '{bindingId}' on '{action}'", this);
return false;
}

return true;
}

可视化Editor定义

可视化操作UI脚本和Editor脚本关联较深,贴上脚本

RebindActionUI.cs

RebindActionUIEditor.cs

复合Composite

对于WASD这样的特殊类型,被称为复合体,在Unity中显示的内容如下图所示

image-20250111140931289

!!重要!!!

这种复合体虽然并不是真正起作用的部分,但是仍然要占用一个索引

在脚本中,可以使用

1
action.bindings[bindingIndex].isComposite

来判断一个action是不是一个复合体

同样的,对于复合体的子元素,可以使用

1
action.bindings[bindingIndex].isPartOfComposite

来判断

一套复合体拆分判断

在给定链接的教程中,对于一个复合体composite的重定义方式采用的是 一起 的形式,这里稍作修改,变为单个判断

关键查重代码补充如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/// <summary>
/// 重复绑定检查,取消对一个composite进行直接控制
/// </summary>
/// <param name="action"></param>
/// <param name="bindingIndex"></param>
/// <param name="isPartOfCompsite"></param>
/// <returns></returns>
private bool CheckDuplicateBindings(InputAction action, int bindingIndex,bool allCompositeParts = false)
{
InputBinding newbinding = action.bindings[bindingIndex];

foreach (var binding in action.actionMap.bindings)
{
if (binding.action == newbinding.action)
{
//不跳过同一组的action
// continue;
}

//关键性补充代码
//查重但是排除自己
if (binding.effectivePath == newbinding.effectivePath && binding.id != newbinding.id)
{
//找到重复绑定的元素了
return true;
}
}


if (allCompositeParts)
{
for (int i = 1; i < bindingIndex; i++)
{
if (action.bindings[i].effectivePath == newbinding.overridePath)
{
//找打重复绑定的元素了
Debug.unityLogger.Log($"Found duplicate binding '{action.bindings[i].name}'");
return true;
}
}
}

return false;
}

补充

获取第一个有效值

1
action.controls[0];

改代码会遍历一个action下所有可用的blinding,默认会排除占用一个索引的复合composite父体,返回第一个在本设备上可用的blinding

OverridePath和effectivePath

当overridePath有效的时候,effectivePath返回的就是override,否则就是原来的

重置

1
2
3
4
foreach (var action in this.m_inputActionAsset)
{
action.RemoveAllBindingOverrides();
}