赞
踩
声明:
1. 本文介绍了Unity引擎的插件Input System使用方法,参考版本为1.4.1
2. 本文参考的官方文档:
工具栏菜单: Window > Package Manager
Package Manager > 搜索 > Input System → 点击安装
安装后弹出警告窗口
警告:Input System与Unity原生输入系统不兼容
是:启用Input System,禁用原生输入系统
否:不启用Input System
工具栏菜单: Edit > Project Settings
Project Settings > Player > Other Settings > Configuration > Active Input Handling* → 启用/禁用Input System
新输入系统的使用可以归纳为两个步骤:
(1). 创建行为资产 (Input Action Assets),绑定输入控件
(2). 编写自定义脚本,定义用于响应输入事件的回调函数
输入系统将不同种类的输入抽象为Control。Control表示输入值的来源,例如,某个float值来源于键盘上的某个按键,某个Vector2值来源于鼠标单帧的位移,某个Vector2值来源于手柄上的摇杆。
控件路径:输入系统使用控件路径查找Control,一个Control的可以由一条控件路径唯一表示。
路径语法如下:
component/component...
写法类似于文件的系统路径。每个路径由一个或多个由正斜杠分隔的组件组成
组件语法如下:
<layoutName>{usageName}controlName#(displayName)
组件多个字段构成,每个字段都是可选的,但必须至少存在一个字段。所有字段都不区分大小写。
字段的用途如下:
字段 | 描述 | 举例 |
<layoutName> | 设备级别的名称 | <Keyboard>/space |
controlName | 控件级别的名称 | <Keyboard>/a |
{usageName} | 用于设备层(第一层):要求设备具有给定用途 | 用于设备层:<XRController>{LeftHand}/trigger |
#(displayName) | 要求设备或控件具有给定的显示名称 | <Keyboard>/#(a) |
可以使用*代替某个字段,表示任何设备或控件
输入系统将针对一系列输入的响应策略抽象为Action(行为)。Action是输入系统的核心,系统通过设计Action将物理(系统如何感知设备传来的输入信号)与逻辑(系统收到信号后如何响应)进行解耦。开发者在编写响应代码时,不需要考虑如何监听设备,只需要与Action进行对接即可。
阶段事件:
Action为开发者提供了5种事件,开发者需要自定义回调函数,以委托的形式监听这些事件。当Action绑定的Control收到输入信号时,Action会触发事件交互事件(Started, Performed, Canceled),当Action被启用或禁用时,也会触发相应事件(Waiting, Disabled)。
阶段事件的触发时机如下:
阶段 | 描述 |
Disabled | Action被禁用,拒绝进行交互 |
Waiting | Action被激活,等待进行交互 |
Started | 交互开始 |
Performed | 交互完成 |
Canceled | 交互结束(完成后)或取消(完成前) |
输入系统将Action与Control之间的连接抽象为Binding。Binding包含一条指向Control的控件路径,多个Binding可以指向同一个Control,一个Action可包含多个Binding。系统收到某个控件输入的数据时,会驱动所有绑定了该控件的Action进行响应。
行为资产是包含Action及其关联的Binding和控制方案的文件。文件的扩展名为 .inputactions ,以纯 JSON 格式存储。输入系统中行为资产与实现代码是相互独立的,行为资产仅作为存储绑定信息的容器,实现代码被放置在UnityEngine.InputSystem命名空间下,开发者需要使用PlayerInput组件或自己编写脚本来使用自己的行为资产。
Control的状态值以回调函数参数的形式传递给逻辑,参数的数据类型取决于Control的类型,如按钮的状态值数据类型为float(按钮感应按压的模拟信号值),手柄摇杆的状态值数据类型为Vector2(向量的方向表示摇杆的方向)。对于事件驱动的响应,状态值可以在回调函数中InputAction.CallbackContext类型的参数中获取,对于消息驱动的响应,状态值可以在回调函数中InputValue类型的参数中获取。
行为资产一般通过Input Actions编辑器创建,也可以通过脚本直接创建,本文仅介绍编辑器的使用方法。
Project菜单: Create > Input Actions → 双击Input Actions资产打开Input Actions编辑器
编辑器的操作界面如下
功能:
(1).控制方案指定输入系统要监听哪些外部设备的信号,系统仅关注这些设备传来的信号。
(2).单个资产可以添加多个控制方案,允许开发者根据不同类型的设备对Binding集合进行批量启用或禁用。例如,角色的移动射击瞄准可以通过键鼠来操控,也可以通过手柄来操控,但一名玩家同时只能选择其中一种方案来操控角色,如果系统既监听键鼠信号又监听手柄信号,会造成CPU资源的浪费,开发者可将键鼠相关Binding纳入键鼠控制方案,手柄相关Binding纳入手柄控制方案,游戏运行时,只选择一种控制方案,激活当前控制方案的Binding,禁用其余控制方案的Binding。
(3).方便开发者修改资产。选择一种控制方案后,界面将仅显示与此控制方案相关的Binding。
用法:
(1).Control Schemes的管理
点击左上角菜单 → (Add|Edit|Duplicate|Delete) Control Scheme
添加|编辑|复制|删除 一个设备
Control Schemes弹窗如下
Requirements: 列表中的每种类型设备可以选择为Optional或Required
Optional: 可选的(官方未给出说明)
Required: 必要的(官方未给出说明)
(2).Control Schemes的过滤显示
点击工具栏第一个菜单项
→ 选择一种Control Scheme
Actions窗口将仅显示与该Control Schemes相关的Binding
→ 选择All Control Schemes
Actions窗口将显示全部Binding
点击工具栏第二个菜单项
→ 选择一种Device
Actions窗口将仅显示与该Control Schemes相关且设备为Device的Binding
→ 选择All Devices
Actions窗口将仅显示与该Control Schemes相关的所有Binding
功能:
单个资产可以添加多个Action Map,允许开发者根据当前使用情景对Action集合进行批量启用或禁用。例如,键盘中的方向键在游戏情景中用于控制角色移动,在UI情景中用于切换当前选中的UI控件,如果两个使用情景不同Action依赖于同一个Control,会造成逻辑混乱,开发者可以将游戏情景下的Action纳入游戏Action Map,将UI情景下的Action纳入UI Action Map,根据不同的情景,激活某个Action Map,禁用其余Action Map。
用法:
点击子视图右上角的加号即可
功能:
管理多个Binding与Composite,关联多个Control,为开发者自定义回调函数提供监听的事件。
用法:
(1). Action Type
交互事件的触发时机与Action类型的关系,以及其他细节如下:
Action Type | Value(值) | Button(按钮) | Pass-Through(直通) |
Started | 控件状态值离开默认值时触发 | 按钮被按下,按压值离开0时触发 | 仅在Action被启用时触发 |
Performed | 控件状态值改变时触发 | 按钮被按住,按压值达到阈值时触发 | 控件状态值改变时触发 |
Canceled | 控件状态值回到默认值时触发 | 按钮被松开, | 仅在Action被禁用时触发 |
控件消歧 | √ | √ | × |
初始状态检查 | √ | × | √ |
按压值:处于[0,1]的float型模拟信号,用于感应按钮是否被按压,按压值达到按压阈值时,按钮才能视为被按下
控件消歧:如果Action绑定了多个Control,选择近期被响应最频繁的控件作为主Control,此Action触发的回调函数将带有来自该Control的参数。
初始状态检查:启用 Action时,Action绑定的Control可能已经具有非默认状态,系统依次检查所有被绑定到此Action的Control,并立即响应处于非默认状态下的控件。
(2). Control Type
限制在界面设置绑定时显示的Control类别,限制哪些Control可以与其绑定的Action进行交互
Control Type | 描述 |
Axis | 一维浮点轴 |
Button | 按钮 |
Key | 键盘按键 |
Vector2 | 二维向量 |
Vector3 | 三维向量 |
Quaternion | 四元数 |
Integer | 整数 |
Stick | 摇杆 |
Dpad | 手柄四向按钮 |
Touch | 触摸屏 |
功能:
管理一个指向Control的控件路径
用法:
Path:控件路径
Use in control scheme:当前Binding在哪些控制框架中生效
功能:
多个Control同时驱动以模仿一个不同类型的Control。Composite包含多个Binding,这些被绑定Control的状态值会组合在一起成为一个新状态值传递给逻辑。
用法:
(1). Composite Type
Composite Type | 新状态值的数据类型 | 描述 |
1D Axis (一维轴) | float | 由两个按钮Control组成一维轴,分别代表正负 |
2D Vector (二维向量) | Vector2 | 由四个按钮Control组成二维向量,分别代表上下左右 |
3D Vector (三维向量) | Vector3 | 由六个按钮Control组成三维向量,分别代表上下左右前后 |
One Modifier(单修饰器) | 取决于Control的类型 | 按住一个按钮Control后,被修饰Control才能被Action响应 |
Two Modifier(双修饰器) | 取决于Control的类型 | 按住两个按钮Control后,被修饰Control才能被Action响应 |
Button With One Modifier | float | 同One Modifier,被修饰Control是按钮控件 |
Button With Two Modifier | float | 同Two Modifier,被修饰Control是按钮控件 |
Composite下的子Binding可以设置不同的组合类型
1D Axis,2D Vector,3D Vector下Binding指向的Control在Composite中扮演的角色及其表示含义:
Composite Part | 1D Axis | 2D Vector | 3D Vector |
Negative | -1 | — | — |
Positive | 1 | — | — |
Up | — | (0,1)(+Y) | (0,1,0)(+Y) |
Down | — | (0,-1)(-Y) | (0,-1,0)(-Y) |
Left | — | (-1,0)(-X) | (-1,0,0)(-X) |
Right | — | (1,0)(X) | (1,0,0)(X) |
Forward | — | — | (0,0,1)(+Z) |
Backward | — | — | (0,0,2)(+Z) |
1D Axis的附加属性:
1D Axis的属性 | 描述 |
Which Side Wins | 同时驱动表示正负的两个Control时,如何处理 |
Min Value | 1D Axis 最小值,默认-1 |
Max Value | 1D Axis 最大值,默认1 |
Which Side Wins | 描述 |
Neither | 返回 0 |
Positive | 返回 Max Value |
Negative | 返回 Min Value |
2D Vector和3D Vector的附加属性:
Mode选项 | 描述 |
Analog(模拟控制) | 将按钮Control的按压值原样进行组合 |
Digital(数字控制) | 根据按钮是否被按下转化为0或1再进行组合 |
Digital Normalized(归一化数字控制) | 同Digital,组合后的向量会被归一化 |
功能:
交互策略表示Control状态值触发Action交互事件的某种方案。为Binding或Action添加多种交互策略,添加到Action的交互策略会作用到Action下所有Binding上。如果Binding没有设置交互策略,则根据Action的类型使用默认的交互策略。
用法:
Press Point(按压阈值):
设置此值会覆盖系统默认的按压阈值,仅对当前Binding或Action生效。控件的按压值达到按压阈值时,按钮才能视为被按下。
(1). Press(按下)
按钮的交互策略,比按钮类型Action的默认交互策略变化更加灵活。
交互事件的触发时机与Press类型的关系:
Trigger Behavior | Press Only | Release Only | Press And Release |
Started | 按压值离开0时触发 | ||
Performed | 按压值达到阈值时触发 | 按压值已达到阈值,而后落回阈值内时触发 | 达到阈值和落回阈值内都会触发 |
Canceled | 如果按压值已达到阈值,按压值落回阈值内时触发 | 按压值回到0时触发 |
(2). Hold(按住)
需要使用者按住控件持续Hold Time秒来完成交互。
Hold Time:从按钮被按下(按压值达到阈值)开始计时,持续Hold Time秒后即可完成交互。
交互事件的触发时机如下:
Callbacks | |
Started | 按压值达到阈值时触发 |
Performed | 按压值达到阈值持续Hold Time秒后触发 |
Canceled | 按压值达到阈值后,落回阈值内时触发 |
(3). Tap(敲击)
需要使用者按下控件后在Max Tap Duration秒内释放来完成交互
Max Tap Duration:按钮被按下(按压值达到阈值)到按钮被松开(按压值落回阈值内)的时间必须<Max Tap Duration才能满足交互条件。
交互事件的触发时机如下:
Callbacks | |
Started | 按压值达到阈值时触发 |
Performed | 按压值达到阈值后,在Max Tap Duration秒内落回阈值内时触发 |
Canceled | 按压值达到阈值持续Max Tap Duration秒后触发 |
(4). Slow Tap(缓慢敲击)
需要使用者按下控件持续Min Tap Duration秒后释放来完成交互
Min Tap Duration:按钮被按下(按压值达到阈值)到按钮被松开(按压值落回阈值内)的时间必须≥Min Tap Duration才能满足交互条件。
交互事件的触发时机如下:
Callbacks | |
Started | 按压值达到阈值时触发 |
Performed | 按压值达到阈值持续Min Tap Duration秒后,落回阈值内时触发 |
Canceled | 按压值达到阈值后,在Min Tap Duration秒内落回阈值内时触发 |
(5). Multi Tap(连续敲击)
需要使用者连续按下并释放控件Tap Count次来完成交互,按下控件后必须在Max Tap Duration秒内释放,上一次释放控件到下一次按下控件的间隔时间不能超过Max Tap Spacing秒。
Tap Count:连续敲击的次数
Max Tap Spacing:上一个Tap结束,即按钮被松开(按压值落回阈值内),到下一个Tap开始,即按钮被按下(按压值达到阈值)的时间必须<Max Tap Spacing,否则交互失败
Max Tap Duration:按钮被按下(按压值达到阈值)到按钮被松开(按压值落回阈值内)的时间必须<Max Tap Duration,否则交互失败。
交互事件的触发时机如下:
Callbacks | |
Started | 按压值达到阈值时触发 |
Performed | 当前交互未触发过Canceled,按压值第Tap Count次落回阈值内时触发 |
Canceled | 当前交互未触发过Performed, |
功能:
处理策略表示Control状态值的一些数值处理方法,处理后的结果作为Action回调函数的参数供开发者访问。添加在Binding或Action上,添加到Action的处理策略会作用到Action下所有Binding上。如果Binding没有设置处理策略,则不作任何处理,直接使用Control的状态值作为回调函数的参数。
用法:
处理策略的详细信息如下:
处理类型 | 参数类型 | 附加属性 | 描述 |
Clamp | float | Min,Max | 将输入值钳制在[Min,Max]范围内 |
Invert | float | — | 反转输入值(求相反数) |
Invert Vector 2 | Vector2 | InvertX, | InvertX为True:反转向量的x轴 |
Invert Vector 3 | Vector3 | InvertX, | InvertX为True:反转向量的x轴 |
Normalize | float | Min,Max, | 如果Min≥Zero,[Min..Max]无符号归一化为[0..1] |
Normalize Vector 2 | Vector2 | — | 将二维向量归一化,使其模长为1 |
Normalize Vector 3 | Vector3 | — | 将三维向量归一化,使其模长为1 |
Scale | float | Factor | 将Factor与输入值相乘 |
Scale Vector 2 | Vector2 | X,Y | 将X与x轴值相乘,将Y与y轴值相乘 |
Scale Vector 3 | Vector3 | X,Y,Z | 将X与x轴值相乘,将Y与y轴值相乘,将Z与z轴值相乘 |
Axis Deadzone | float | Min,Max | 输入值的绝对值小于Min时为0,大于Max时为1或-1 |
Stick Deadzone | Vector2 | Min,Max | 二维向量的模长小于Min时为0,大于MAX时被归一化为1 |
Deadzone(死区):当控件未被驱动时,由于模拟信号的误差,并不总是准确地向系统传递默认状态值,设置死区以避免这种现象。当前状态值接近默认状态值时(进入死区),被直接赋值为默认状态值。
功能:
PlayerInput组件代表一个单独的玩家。 组件与一个Action Map(行为映射)相关联,当某个被绑定在Action的Control收到输入信息时,以事件驱动或消息驱动的方式通知逻辑层,执行开发者编写的响应代码。
用法:
Actions
即Input Action Assets 行为资产
Default Scheme: 指定行为资产下的某个控制方案,作为当前组件默认的控制方案
Default Action Map: 指定行为资产下的某个行为映射,作为当前组件默认的行为映射
UI Input Module
InputSystemUIInputModule组件。用于驱动UI系统,PlayerInput 和 InputSystemUIInputModule 组件必须引用相同的Input Action Assets才能正常工作,PlayerInput 的Action以相同的效果施加于InputSystemUIInputModule 。
Camera
玩家摄像机
Behavior
组件收到Control的输入并触发Action的阶段事件时,以什么方式通知逻辑
Behavior | 描述 |
Send Messages (消息驱动响应) | 假设行为资产中包含一个名为"Fire"的Action。 |
Broadcast Messages (消息驱动响应-广播) | 同Send Messages,此外,在场景树中以此GameObject为根,向下广播,子树的所有GameObject节点都会执行SendMessage()。 |
Invoke Unity Events (事件驱动响应-UnityEvent) | 编辑时,选择此选项将出现可视化的Events折叠框,开发者需要将某个GameObject拖进槽内,并选择一个方法作为Action的回调函数,假设方法为"void CustomMethod(InputAction.CallbackContext context){}"。 |
Invoke CSharp Events (事件驱动响应-原生event) | 开发者需要手动为交互事件注册回调函数。 首先,访问PlayerInput组件,在actions字典中查询并获取相关InputAction实体。 InputAction提供started,performed,canceled等C-Sharp原生的event事件。 然后,将自定义回调函数直接注册到event中即可。 |
Invoke Unity Events的可视化界面如下:
- // 此脚本必须与相关Player Input组件挂载到同一个GameObject
- public class MyPlayerInputScript : MonoBehaviour
- {
- // "Fire" Action 对应 "OnFire"方法
- void OnFire(InputValue value)
- {
- var v = value.Get<float>();
- Debug.Log(string.Format("Fire Performed:{0}", v));
- }
- // "Move" Action 对应 "OnMove"方法,
- void OnMove(InputValue value)
- {
- var v = value.Get<Vector2>();
- Debug.Log(string.Format("Move Performed:{0}", v));
- }
- }
- // 此脚本可来自任意GameObject
- class MyPlayerInputScript : MonoBehaviour
- {
- // "MyCallback1"和"MyCallback2"方法 需要被外界访问(public)
- // "MyCallback1"方法 需要挂载到 UnityEvent "Fire" 槽中
- public void MyCallback1(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<float>();
- if (context.started) { Debug.Log(string.Format("Fire Started:{0}", v)); }
- if (context.performed) { Debug.Log(string.Format("Fire Performed:{0}", v)); }
- if (context.canceled) { Debug.Log(string.Format("Fire Canceled:{0}", v)); }
- }
- // "MyCallback2"方法 需要挂载到 UnityEvent "Move" 槽中
- public void MyCallback2(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<Vector2>();
- if (context.started) { Debug.Log(string.Format("Move Started:{0}", v)); }
- if (context.performed) { Debug.Log(string.Format("Move Performed:{0}", v)); }
- if (context.canceled) { Debug.Log(string.Format("Move Canceled:{0}", v)); }
- }
- }
- class MyPlayerInputScript : MonoBehaviour
- {
- private void Awake()
- {
- // 需要访问PlayerInput组件和相关的Action
- PlayerInput playerInput = GetComponent<PlayerInput>();
- InputAction hit = playerInput.actions["Fire"];
- InputAction move = playerInput.actions["Move"];
-
- // 手动注册回调函数
- hit.started += OnFireStarted;
- hit.performed += OnFirePerformed;
- hit.canceled += OnFireCanceled;
- move.started += OnMoveStarted;
- move.performed += OnMovePerformed;
- move.canceled += OnMoveCanceled;
- }
- void OnFireStarted(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<float>();
- Debug.Log(string.Format("Fire Started:{0}", v));
- }
- void OnFirePerformed(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<float>();
- Debug.Log(string.Format("Fire Performed:{0}", v));
- }
- void OnFireCanceled(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<float>();
- Debug.Log(string.Format("Fire Canceled:{0}", v));
- }
- void OnMoveStarted(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<Vector2>();
- Debug.Log(string.Format("Move Started:{0}", v));
- }
- void OnMovePerformed(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<Vector2>();
- Debug.Log(string.Format("Move Performed:{0}", v));
- }
- void OnMoveCanceled(InputAction.CallbackContext context)
- {
- var v = context.ReadValue<Vector2>();
- Debug.Log(string.Format("Move Canceled:{0}", v));
- }
- }
工具栏菜单: Edit > Project Settings
Project Settings > 右侧选项栏 > Input System Package
功能:
全局设置信息将以Assets文件的形式保存,文件的扩展名为.inputsettings。导入插件时,系统会在根目录自动生成一个默认的InputSystem.inputsettings。开发者可手动创建多个Input Settings资产,但一个项目只能选择一个Input Setting资产来使用。
用法:
(1). 创建Input Settings资产
点击右上角齿轮 → New Settings Asset...
(2). 选择Input Setting资产
点击右上角齿轮 → 选择一个已有的Input Setting资产
Update Mode
输入系统何时处理输入。
类型 | 含义 | 描述 |
Process Events | 动态帧处理 | 系统在Update()函数调被用时自动处理输入 |
Process Events | 固定帧处理 | 系统在FixedUpdate()函数被调用时自动处理输入 |
Process Events | 手动处理 | 系统不会自动处理输入 |
Background Behavior
应用程序失去/获得焦点时(应用程序在前台/后台)应该如何处理,此设置仅支持Android和iOS 等移动端平台。
类型 | 描述 |
Reset And Disable | 失去焦点时,软重置并禁用没有canRunInBackground标记的输入设备 |
Reset And Disable | 失去焦点时,软重置并禁用所有输入设备 |
Ignore Focus | 失去焦点时,不做任何事 |
Filter Noise On Current
某些设备的输入中存在噪音,即使没有与它们交互,也会传来输入信号。为解决上述问题,启用此选项来过滤噪声。启用此选项会有增加一些开销,默认为禁用。
启用此选项:设置死区,系统接收到位于死区内的状态值时,将其变为默认状态值。
Compensate Orientation
对于移动端的开发,访问陀螺仪的状态值时,启用此选项以使陀螺仪状态值由三维映射为二维(朝向z轴)。
启用此选项:传感器报告的旋转值将围绕 Z 轴旋转。
屏幕基准方向如下所示:
屏幕朝向 枚举 | 旋转值受到的影响 |
ScreenOrientation.Portrait | 屏幕纵向(上):旋转值不变 |
ScreenOrientation.PortraitUpsideDown | 屏幕纵向(下):旋转值转180度 |
ScreenOrientation.LandscapeLeft | 屏幕横向(左):旋转值转90度 |
ScreenOrientation.LandscapeRight | 屏幕横向(右):旋转值转270度 |
此选项影响的传感器:
Gyroscope
GravitySensor
AttitudeSensor
Accelerometer
LinearAccelerationSensor
Default value properties
全局变量 | 描述 |
Default Deadzone Min | Stick Deadzone或Axis Deadzone处理策略的默认Min。 |
Default Deadzone Max | Stick Deadzone或Axis Deadzone处理策略的默认Max。 |
Default Button Press Point | 交互策略的默认按压阈值。 |
Default Tap Time | Tap交互策略的默认Max Tap Duration。 |
Default Slow Tap Time | Slow Tap交互策略的默认Min Tap Duration。 |
Default Hold Time | Hold交互策略的默认Hold Time。 |
Tap Radius | 触摸屏设备上两个手指点击之间的最大距离,系统将其视为同一触摸的点击(而不是新的触摸)。 |
Multi Tap Delay Time | Multi Tap交互策略的默认Max Tap Spacing。 |
Supported Devices
设置此项目支持的设备集以在Input Action Assets编辑器的Binding可视化选项中屏蔽掉无需被此项目考虑的设备。
待更新
InputSystemUIInputModule 组件
PlayerInputManager组件
InputDebugger
自动生成和JSON文件
运行时修改Action
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。