新输入系统的名字就叫InputSystem,新是相对于旧的InputManager来说的
核心思想是添加一个动作(action)的概念,代码只监听动作的触发,由动作去绑定物理输入,这样无论什么平台,无论如何重新指定物理输入,我们都不需要修改代码。
同时也可以将同一个物理输入同时绑定到不同的输入动作集中,随时切换输入动作集,例如上车后,从走路的动作集切换到开车的动作集。
此外还提供了一些方便的功能,例如使用代码重新绑定按键、屏幕按键等、检测设备接入拔出、组合键、次要绑定等。
InputSystem不是默认安装的,我们需要使用packagemanager来安装他。
建议使用2019之后的版本
打开packageManager,在unityRegistery里搜索,然后安装即可,安装过程中你的编辑器会需要重启一次。
如果你打开包管理器不显示包,那么你需要退出编辑器,刷新一下通行证,重新打开即可。
有两种方法可以创建输入
1 通过Project面板右键菜单Create/InputAction创建一个新的输入资产,这将创建一个全新的资产。
2 为一个物体添加一个PlayerInput组件,点击create按钮,这会创建一个带有默认输入的资产。
创建新的输入资产的时候必须小心的命名,不要随便起个名字,因为之后创建的带有输入动作的c#脚本会叫这个名字,瞎起名字是给自己找麻烦
这个面板的作用是管理一个InputActionAssets的action和对应的映射。
双击一个输入资产即可打开这个面板。
以下是详细解释
默认是只有AllControlSchemes的,可以使用AddControlScheme创建新的输入方案,随后可以为action的一个物理输入指定自己的输入方法,当我们切换输入方案时,就可过滤这个方案下的action了,注意方案只是一个名字,没有任何实际意义,你完全可以起一个名字叫gamepad的方案,但是为keyboard action指定这个方案。
删除控制方案时,如果由物理输入会让我们选择是否要连同绑定的物理输入一同删除,选yes会删除所有指定为当前方案的物理输入绑定,选no只会删除这个控制方案,而保留绑定的物理输入
不建议使用Auto-Save,因为我们需要为aciton创建一个c#文件才能在脚本中调用,使用了Auto-Save时,如果我们已经创建了这个脚本,每当我们做出改变,都会重新编译脚本,这将非常痛苦
我们可以在这里定义不同的映射集,走路动作映射集、开车动作映射集、UI动作集等
点击+号即可创建新的动作集
这两个要一起看
actions: 一个actionMaps里的所有action,用于创建action并为action绑定物理按键
Properties: action或binding的属性
点击atcions的加号即可创建一个新的action(绿色),新action默认自带一个绑定(蓝色),只不过目前这个绑定还没有绑定任何物理按键
右键action即可删除action
点击action后的+号并选择一个绑定类型即可创建一个新的bingding(蓝色)
右键bindging即可选择删除
Action 这是action属性栏里第一个属性
创建好aciton后,我们第一步要确定action的类型,选中一个action(绿色),右侧属性面板会显示这个action的选项
有value和button和Pass Through三种类型
注意修改了aciton的类型后,会影响action可以创建的物理输入的选项
Interactions 如何交互
可以指定这个action如何交互
点击+号添加一个新的交互方式
常用的交互有Hold按住一段时间后触发,MultiTop,多次点击等,见名知意,不多废话。
如果什么都不加,则为默认的交互方式。
Processors 定义如何处理获取到的值
可选项有
创建绑定的注意事项
点击一个action后的+号,然后选择一个具体类型,即可创建一个绑定
根据action的类型不同,可以选择的binding类型是不同的
当action的ActionType为Button时,我们可以创建的类型有
当action为Value类型时,我们可以创建的类型通常有Binding和Up/Down/Left/Right,显然这是用来用键盘控制方向的
这里绑定类型过多,无法全部列举,但我们最常用的就是Button和键盘摇杆的轴输入
绑定一个物理输入
新创建的binding是没有按键绑定的,需要我们手动绑定。
选中一个binding,点击他的属性栏里的Binding分类,然后点击Path/Listen,然后按下按键或移动摇杆,再从监听到的列表里点选我们需要的输入即可
例如我按下了space键,我就在列表里选择space键,注意你可以按下多个按键。
对于摇杆,例如你坚挺了XBOX的摇杆,你可选择这个动作是仅用于Xbox还是通用的,如果是通用的,使用其他品牌的摇杆按下对应的键同样可以起作用,否则只会相应Xbox摇杆,如下图,第一选项是通用输入,第二选项是仅相应Xbox摇杆。
为绑定选择一个ControlSchemes
如果我们之前建立了一个控制方案,我们可以为这个Binding指定属于的控制方案,这方便我们过滤。
如何新建控制方案可以参考本章“区域一”部分。
Interactions和Processors
和action相同,只不过banding的这两个选项会覆盖action的。
这里介绍三中监听输入的方式,但是只有第三种是重要的,前两种知道就行。
虽然inputSystem提供了acion这个概念,但我们同样可以直接去访问键盘按键
首先引入nameSpace
using UnityEngine.InputSystem;
//键盘
if (Keyboard.current.aKey.wasPressedThisFrame)
{
print("A键按下");
}
//鼠标输入
print(Mouse.current.delta.ReadValue());
//鼠标按下
if(Mouse.current.leftButton.wasPressedThisFrame)
{
}
这种用法最好只用来做测试,不要真的用它做项目,因为他还没InputManager好用,至少InputManagerAPI更好找。
为一个物体挂载一个PlayerInput组件,然后选择一个InputAcionsAssets。
使用DefaultMap选择一个acitonMaps。
使用Behavior来选择一个消息传递方式,这里推荐用第3,4个,以下分别介绍这两种模式
InokeUnityEvnets:
这个模式的优点在于可以直接拖拽事件
切换到Behavior的第三个模式后,会出现Events选项,其中Player和UI是我创建的两个actionMaps,其中Jump和 Movement是Player这个acionMaps里的两个action,我们需要如何只需像给UIButton绑定事件一样,为action拖拽事件即可。
我们可以这样声明事件:
//有参
public void Jump(InputAction.CallbackContext context)
{
//Debug.Log(context);
//context.performed||context.started||context.canceled 按下 开始按 松开
if (context.performed)//只在按下时触发
{
rig.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
}
//无参
public void Jump()
{
rig.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
需要注意的是,一个按钮被按下时,会触发3次事件,因为一个按钮包含三个阶段,开始按/按下/松开,所以我们最好用带参的方法绑定事件,并自行在方法中判断阶段
Inoke CSharp Evnets
这种方式需要我们在脚本里查找inputManager组件,并绑定委托,类似于用脚本为UIButton绑定事件
private Rigidbody rig;
private PlayerInput playerInput;
private void Start()
{
playerInput = GetComponent<PlayerInput>();
//查找组件的方式切换输入控制集
playerInput.SwitchCurrentActionMap("Player");
playerInput.onActionTriggered += PlayerInput_onActionTriggered;
}
private void PlayerInput_onActionTriggered(InputAction.CallbackContext obj)//使用InvokeCSharpEvents模式监听事件
{
Debug.Log(obj);
}
这是唯一推荐使用的方式
首先我们要生成c#文件
找到InputActionAssets,勾选生成C#类,即可自动生成c#类,此时最好关闭InputAcionts面板的Auto-Save选项,否则每次我调整输入,都会立刻重新生成这个类
生成的c#类名字和InputAcionsAssets名字相同,这就是为什么不要乱起名字。
在代码中监听action按键输入,获取value类型的值
目前的输入资产
编写脚本
PlayerInputActions playerInputActions;
private void Start()
{
playerInputActions = new PlayerInputActions();注意是new 一个对象,不是查找组件
playerInputActions.Player.Enable();//激活一个控制集 注意必须要激活一个acitonMaps
playerInputActions.Player.Jump.performed += Jump;//绑定事件
playerInputActions.Player.Movement.performed += Movement_performed;//按一下动一下,做移动输入应该按下方FixedUpdate里的方式,这里只是演示如何做值类型的输入监听
}
private void FixedUpdate()
{
//直接监听value类型的action的输入
Vector2 inputVector = playerInputActions.Player.Movement.ReadValue<Vector2>();
Debug.Log(inputVector);
}
//注册跳跃的方法
public void Jump(InputAction.CallbackContext context)
{
Debug.Log(context);
}
//注册移动的方法
public void Movement_performed(InputAction.CallbackContext context)
{
Vector2 inputVector = context.ReadValue<Vector2>();//读取value类型的action,注意泛型要用和输入匹配的类型
float speed = 5f;
rig.AddForce(new Vector3(inputVector.x, 0, inputVector.y) * speed, ForceMode.Force);
}
非常简单
playerInputActions = new PlayerInputActions();
//C#方式切换输入控制集
playerInputActions.UI.Disable();//禁用一个actionMaps
playerInputActions.Player.Enable();//启用一个actionMaps
//重新绑定按键,重新绑定按键前,需要确保已经关闭了所有的输入动作集,否则一旦开启监听,就会立刻绑定当前输入的值,这里边肯定有我们不想要的值,例如鼠标位置,滑移的摇杆等
playerInputActions.Player.Disable();
playerInputActions.UI.Disable();
playerInputActions.Player.Jump.PerformInteractiveRebinding(0)//参数0 修改首要绑定 1 修改次要绑定 默认为0
.WithCancelingThrough(Keyboard.current.escapeKey)//指定一个按键用于取消重新绑定
.OnCancel(callBack =>
{
print("取消绑定");
callBack.Dispose();//取消绑定要释放资源
playerInputActions.Player.Enable();//重新激活输入动作
})
.WithControlsExcluding("Mouse")//禁止绑定鼠标按键 参数的值可以从绑定界面看一下都有什么输入分类
.OnComplete(callback =>
{
Debug.Log("结束绑定");
callback.Dispose();//完成重新绑定后需要释放对象
playerInputActions.Player.Enable();//重新激活输入动作
})
.Start();//开始监听重新绑定的按键
如果我们不手动保存重新绑定的按键,那么下次启动时,还是会使用最开始的按键
我们手动保存了按键后,每次启动,都需要读取,并且重新赋值给inputsystem
在绑定的OnComplete()里添加保存
.OnComplete(callback =>
{
Debug.Log("结束绑定");
Debug.Log(callback);
//inputSystem1.1版本以后的保存重新绑定方式
string rebinds = callback.action.SaveBindingOverridesAsJson();
PlayerPrefs.SetString("rebinds", rebinds);//静态方法,参数1 固定字符串,表示重新绑定
print("重新绑定的内容" + rebinds);
callback.Dispose();//完成重新绑定后需要释放对象
playerInputActions.Player.Enable();//重新激活输入动作
})
``
在游戏启动时读取上次保存的重新绑定json
```csharp
playerInputActions = new PlayerInputActions();
//C#方式切换输入控制集
playerInputActions.Player.Enable();
string rebinds = PlayerPrefs.GetString("rebinds");
playerInputActions.LoadBindingOverridesFromJson(rebinds);
playerInputActions.Player.Jump.RemoveBindingOverride();
playerInputActions = new PlayerInputActions();
playerInputActions.Player.Enable();
print(playerInputActions.Player.Jump.name);//action的名字
print(playerInputActions.Player.Jump.GetBindingDisplayString(1));//列出次要绑定 参数为0是首要绑定
print(playerInputActions.Player.Jump.GetBindingDisplayString());//列出action的首要和次要绑定