Unity Input System Step-By-Step 最简教程
#Overview
本教程极大程度的参考了 Unity Learn 上的官方教程[^1],但并不是其翻译版本,而是根据我的学习过程进行相应增删改。
完整工程见:xuejiaW/InputSystemSample: A minimum unity project to illustrate how to use Unity new input system. (github.com)
Unity 有内建的 Input Manager
机制,这一套机制存在了非常久的时间。针对于传统的键盘,鼠标等输入,内置的 Input Manager
可以健壮的处理,但 Input Manager
的可拓展性不高。也因此随着输入设备种类的增多(如各类 XR 设备),Input Manager
无法优雅的解决这些输入。
Input System
是 Unity 为了解决 Input Manager
的上述问题,提供的高可拓展性,高自由配置的新输入解决方案。
对于新工程,Unity 官方都推荐使用 Input System
作为输入的解决方案,但 Input Manager
并不会短期内被废弃,因为历史包袱过重[^2]。
Input System 依赖 Unity 2019.1 及以上版本,本文档基于 Unity 2022.3.15f1 + Input System 1.7 编写
#Get Started
#安装 Input System
首先通过 Unity Package Manager 安装 Input System:
在安装 Package 后,会自动弹出如下窗口,该窗口表示 Input System
启用后需要重启 Editor Backend 才能正常使用,点击 Yes
启用 Input System,此时 Unity Editor 会自动重启:
当 Unity 重启后,根据 Unity 版本的不同,可能内置的 Input Manager
会被关闭,如果要重新启用,可以在 Edit
-> Project Settings
-> Player
-> Other Settings
-> Active Input Handling
中选择 Both
:
至此 Input System 已经被正确安装。
为方便后续的调试,Demo 工程中预先引入了 URP 和一个最简的测试场景,此时的工程的见:A
xuejiaW/InputSystemSample at 7d041a5604c71096b0147cd0ae672557eee517c8 (github.com)
#创建 Input System Assets
为了使用 Input System,推荐先创建 Settings Asset,你需要在 Project Settings
-> Input System Package
中创建相关资源:
该 Settings Asset 作为 Input System 全局的配置,但其并不是必须项。如果未创建该文件 Unity 会使用默认的 Input System 配置。
当点击创建后,会在工程的根目录创建出一个 InputSystem.inputsettings
文件,该文件即是 Input System 的总配置文件。同时原 Input System Package
页面也会包含有一系列的针对于 Input System
的配置项:
选择创建出来的 InputSystem.inputsettings
文件,在 Inspector 中会出现直接跳转到 Input System Settings
的按钮,点击该按钮,同样会跳转到上述 Input System Settings
的配置页面:
你可以随意修改 InputSystem.inputsettings
的位置,并不要求该文件必须在工程根目录下。
此时的工程状态见:
xuejiaW/InputSystemSample at 62aff15fcf5c3479e5a3073af7646a6c2775e043 (github.com)
#查看 Input Debugger 窗口
你可以在 Window -> Analysis -> Input Debugger
中打开 Input Debugger 窗口,该窗口中可以显示当前连接的输入设备:
#使用 Input System
#创建 Input Action Asset
如场景中有如下小球:
为了让其移动,可以为它添加一个 Player Input
组件,在 Player Input
组件上,选择 Create Action
创建出一个 Input Action 资源:
当点击后,会需要你选择保存的路径,选择后,会在该路径下创建出一个 Input Action
资源( Input System.inputactions
),并自动打开该资源的配置窗口,窗口如下所示:
创建出来的 Input Action Asset 资源如下所示,当点击该资源上的 Edit asset
按钮或双击该资源,都将打开上述的窗口:
具体查看 Input Action Asset 中的 Move Action,可以看到其中通过定义了可以通过键盘的 WASD
和 上下左右
触发:
此时按下 WASD
或 上下左右
,会发现小球还 不能 移动,因为此时小球只是 获取 到了输入信息,但还是没有 处理 这些输入信息。
此时工程状态见:
xuejiaW/InputSystemSample at ed81be6f2efcf89c72f287240c9b56ea80a24094 (github.com)
#使用代码控制小球
为了处理 Input System 的输入信息,可以添加 PlayerController
脚本,其实现如下:
1 | using UnityEngine; |
其中的 OnMove
对应 创建 Input Action Asset 后 Asset 中的 Move
Action:
对于 Asset 中任意名称的 Action,都可以通过 On<ActionName>
监听到。
如果 Action 叫做 AAA
,则可以定义 OnAAA
函数监听。
将该脚本挂载在 Player
上,如下所示:
此时小球就可以通过键盘的 WASD
和 上下左右
移动:
此时的工程状态见:
xuejiaW/InputSystemSample at 9cb75b9a8719cc8e695ac32ad786adcc007494d8 (github.com)
#自定义 Action Asset
在上 创建 Input Action Asset 步骤中,创建出来的 Input Actions 是 Unity 默认实现的,即适合于 Player Input
组件的 Actions 资源。
Player Input
组件也是 Unity 内建的读取 Assets 资源的脚本
在这一节,会自定义 Actions 资源,并自定义使用该 Actions 资源的脚本。
#创建自定义 Action Asset
在 Project 面板中,空白处右键选择 Create -> Input Actions
,创建出一个新的 Input Actions 资源:
双击创建的资源(本例中为 BallControls.inputactions
) 后会打开空白的 Input Actions 窗口:
此时点击画面左侧的 +
号可以创建出 Input Action Map,我们将新增的 Input Action Map 命名为 BallPlayer
:
在窗口中间,可以为这个 Input Action Map 创建一些 Input Action,如下过程,创建了 Buttons
这个 Input Action:
在窗口的右侧,可以为 Input Action 创建一系列 Input Binding,如下步骤分别绑定了 GamePad
的 East Button
和 West Button
:
GamePad
的 East
和 West
Button,在 Xbox 控制器上分别对应 X
键和 B
键
你也可以继续为 Buttons
Action 绑定 Keyboard 的 F1
和 F2
按键,步骤如上,当绑定完成后,整个 Buttons
Action 如下所示:
进一步创建 Move
Input Action ,与 Buttons
不同是,Move
需要将 Action Type 设置为 Value
,且 Control Type 为 Vector2
,这表示 Action 会返回 Vector2
数据,即用于平面移动的上下左右数据:
如之前步骤一样,为该 Move
Input Action 绑定 Left Stick
,绑定后结果如下:
也可以将键盘上的按键通过 组合绑定(Composite Bindings) 至 Move
Input Action,如下所示,其逻辑为使用四个按键分别表示 Vector2
四个方向():
分别为上下左右四个方向设定四个按键 K,J,H,L
,结果如下所示:
至此,自定义的 Action Asset 创建完成,其中定义了使用 GamePad
和 Keyboard
两种输入设备,分别控制 Buttons
和 Move
两个 Action。将新建的 BallControls.inputactions
替换掉 Player Input
组件中的 Actions,即可使用新的 Action Asset:
此时运行游戏,可以发现通过手柄的左摇杆和 HJKL
都可以控制小球的移动,而 WASD
则不行了。
这是因为 PlayerController
脚本监听的 Motion
事件在 BallControls.inputactions
中也存在,因此我们定义的左摇杆和 HJKL
四个按键都能响应,即使不修改 PlayerController
也可以正常运行。而原 PlayerInput.inputactions
中的 WASD
我们并没有绑定,所以无法相应。
此时的工程状态见:
xuejiaW/InputSystemSample at 8d994e47fbf7c766c87aa62ce517e7e5bdda031b (github.com)
#创建自定义 Player Input
#手动解析 Actions Asset
自定义一个 BallController
脚本,用于解析刚刚创建的 BallControls.inputactions
,其实现如下:
1 | public class BallController : MonoBehaviour |
可以看到,该脚本直接引用了之前的 InputActionAsset
,并使用了 InputActionAsset.FindActionMap](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.7/api/UnityEngine.InputSystem.InputActionAsset.html#UnityEngine_InputSystem_InputActionAsset_FindActionMap_System_String_System_Boolean_) 找寻之前创建的 BallPlayer
[Input Action Map,并在 OnEnable
和 OnDisable
时启用和禁用该 Input Action Map。
另外脚本中通过 InputActionMap.FindAction](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.7/api/UnityEngine.InputSystem.InputActionMap.html#UnityEngine_InputSystem_InputActionMap_FindAction_System_String_System_Boolean_) 找寻之前创建的 Buttons
和 Move
Action,并监听了 [Input Action 的 performed
事件,触发对应的回调函数 OnButton
和 OnMove
。
至此 BallController
脚本已经完全实现了之前 Player Input
+ PlayerController
的功能,因此在 Player
游戏物体上仅需要 BallController
脚本即可,注意要将之前创建的 BallControls.inputactions
挂载至脚本中:
此时小球可以如同之前一样的通过手柄和键盘控制移动。
此时工程状态见:
xuejiaW/InputSystemSample at f070c14f0671d7c1c702b270f3751aed8c003692 (github.com)
#基于 Actions Asset 自动生成对应类
在 手动解析 Actions Asset 中需要手动管理 Actions Asset
并从中读取 Input Action Map 和 Input Action。
上述的读取过程,会随着 Action Assets
中的数据变更而出现潜在的失效(如命名错误),因此 Unity 提供了从 Action Assets
中自动创建相应脚本的能力,可以简化上述步骤。
可以选择 Action Assets
便选择,并勾选其中的 Generate C# Class
,选择需要创建的类名称,文件和命名空间,并点击 Apply
正式创建脚本:
此时会创建出对应的脚本:
修改之前的 BallController
脚本,以适配自动生成的 BallControls
,如下:
1 | using UnityEngine; |
此时不再需要手动获取 Input Action Map 和 Input Action,只需要使用 <ActionControls>.<ActionMapName>.<Action>
的风格直接访问即可。
此时将之前挂载在 Player
上的的 BallController
脚本换为 BallController_AutoScripts
脚本,并运行,可以看到效果与之前的效果无差别。
此时工程状态见:
xuejiaW/InputSystemSample at a92af1df6ccfb22f2747548d2abf1a08c43a3407 (github.com)