Unity-最新InputSystem学习&该如何使用?
InputSystem安装
打开PackageManager搜索Input System,点击Install进行InputSystem的安装。
安装成功之后会弹出一个启用提示,如下图。提示内容主要是提示:你是否立刻启用新InputSystem,同时禁用掉旧的输入系统。
这里点击Yes,则启用Input System,放弃旧的。我们选择Yes。
以上操作所影响选项是Project Settings-Player中Active Input Handing属性,这里根据个人需求去选择。
同时开启-选择Both,相对方便临时的测试。
Support Device
InputSystem默认支持所有的输入设备,为了用户自定义InputSystem支持我们自定义配置支持的设备列表,如下图所指位置中一旦添加设备时,任何不被归类为支持的设备都会出现在输入调试器中的“不支持设备”下。如果为空,则InputSystem支持所有设备。
通过InputSystem主动获取设备控制
了解相关接口
与InputManager不同的是,InputSystem按照其新的输入系统框架标准来为我们将每种设备各自构建为一个类。如键盘-Keyboard类、鼠标-Mouse类、手柄-GamePad类。
得益于新版输入系统的框架设计,我们可以主动的直接获取到我们设备的状态了。
代码如下:
监听键盘以及手柄:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Qiyu;
using Unity.XR.Qg.Input;
using UnityEngine.InputSystem;
public class PlayerRole : MonoBehaviour
{
public void Update()
{
ListenerInputBehaviour();
}
public void ListenerInputBehaviour()
{
//InputDevice inputDevice=null;
///*
// * //获取当前键盘
// * inputDevice =Keyboard.current
// */
///*
// * //获取当前手柄
// * inputDevice= Gamepad.current
// */
///*
// */
//if (inputDevice==null)
//{
// //当前没有激活的输入设备
// return;
//}
ListenerKeyboardDevice();
}
/// <summary>
/// 监听键盘
/// </summary>
public void ListenerKeyboardDevice()
{
Keyboard keyboard = Keyboard.current;
if (keyboard==null)
{
return;
}
//--按住 有持续过程
bool isPressed = keyboard.aKey.isPressed;//Status:是否按住
isPressed = keyboard.aKey.IsPressed(1/*have arg-pressPoint:float*/);//Status:是否按住
bool onPressed = keyboard.bKey.wasPressedThisFrame;//当前帧是否按下状态
bool onRelease = keyboard.bKey.wasReleasedThisFrame;//当前帧是否刚刚松开状态
float pressPoint = keyboard.aKey.pressPoint;//Status:是否按下
float btnValue = keyboard.aKey.ReadValue();//读取值 按下为1 松开为0 无平滑
//Debug.Log(btnValue);
//Debug.Log(isPressed);
Debug.Log("Status:"+"onPressed-"+onPressed);
Debug.Log("Status:"+"onRelease-"+onRelease);
}
}
监听鼠标与光标
/// <summary>
/// 监听鼠标与光标
/// </summary>
public void ListenerMouse()
{
Pointer pointer = Pointer.current;//屏幕上的光标
pointer.delta.ReadValue();//当前光标距离上一针光标位置的偏移
pointer.position.ReadValue();//当前光标位置
Mouse mouse = Mouse.current;//鼠标
bool leftMBtnIsPressed = mouse.leftButton.isPressed;//Status:鼠标左键是否按住
bool rMBtnIsPressed = mouse.rightButton.isPressed;//Status:鼠标右键是否按住
float middleMPressed = mouse.middleButton.ReadValue();//Status:鼠标中键是否按住 返回[0,1]
Vector2 middleMDelta = mouse.scroll.ReadValue();//鼠标中键滚轮的滚动值,向前滚Y的值为正,向后滚为负。
}
直接从输入设备获取输入快速又方便,但从上面的代码,我们可以看出每种类型的设备都需要访问各自的类型才能获取其状态。这使得以后难以更改哪个设备控件触发游戏中的特定事件。比如我们将要设计一款全平台的射击类游戏,在PC端要求玩家可以使用鼠标左键射击,手机端要求可以点击屏幕开火键射击。如果使用主动获取设备的方式(不队项目进行额外的输入管理),我们无非需要再写入设备来满足其逻辑分支。
有朋友可能会说,如果我就只做一个平台的游戏是不是就可以忽略这个问题了,其实不然,换个例子来说可能更鲜明一点。将全平台游戏换成PC端游戏,现在我们需要玩家不仅可以使用鼠标键盘控制操作,当手柄接入电脑时也要能够进行控制。这个例子与上面所说的影响是一样的,当后期适配平台或适配输入设备时,主动获取设备状态的方法,需要我们在代码逻辑中进行添加与修改来满足适配,不谈变化带来的危险性,其开发效率很低。
有一种方法可以为我们解决这些问题:将操作行为化。
信号行为化
无论对于什么设备来说,我们控制设备所输入的信号,都最终代表某个特定的行为。(满足条件-操作行为),将一类信号转换为行为,这就是信号行为化。
如 射击=点击鼠标左键||点击手柄A键。
满足以上两个信号其中任意一个信号则射击Action为True。
InputSystem正是采用这样的思想,将输入逻辑最简化。
下面看下InputSystem的Action到底是如何使用的?
通过行为间接获取输入
首先InputSystem将Action的配置都放入一个类型为InputActions的文件,同时将配置进行可视化,这样依赖所有的修改都基于可视化窗口对配置文件进行修改,极大得提高我们的开发效率。
创建一个InputActions文件
Project窗口中右键菜单栏中点击InputActions。
打开InputActions窗口
双击打开我们InputActions文件,可看到如下图的界面
详细说明:
ControlSchemes
控制的解决方案(个人的理解是针对平台来提高解决方案),用于关联Action同时对设备相对应的Action进行分类。InputSystem会根据设备类型自动切换方案。
添加ControlSchemes方案-点击我跳转文章
ActionMaps
Actions的映射集合,管理各个映射集合。某一时刻仅能启用一种映射集合,可根据逻辑来切换映射集合。(前提是Action属性里在Use in Control Scheme选项里选中了对应的解决方案,见文章)
Actions
行为集合,用于将输入信号转换为Action(配置某个行为),点击右侧加号可创建Action。
Action添加绑定:点击Action右侧加号,选中某个Bind
Add Binding:普通的绑定,可以绑定一个信号。
Add 1D Axis Composite:一维绑定,两个按钮的组合,返回值为float
Add 2D Vector Composite:二维绑定, 四个按钮的组合,返回值为vector2,例如WASD
Add Button With One Modifier Composite:需要同时按下两个按钮的组合,例如ctrl+1
Add Button With Two Modifier Composite:需要同时按下三个按钮的组合,例如shift+ctrl+1
Properties
Action的属性窗口与Bind属性窗口
Action的属性窗口
Action Type
Value :主要用于状态连续变化的输入,例如鼠标的移动,遥感。
Button :用于每次按下时触发的Action
Pass-Through :类似于Value,区别在于多个设备都绑定这个Action,Pass-Through会发送执行所有设备的输入。(官方文档中提及到两个关键区别,这是其中一个,具体说明见枚举输入操作类型|输入系统|1.3.0 (unity3d.com),这个我也不上搞得)
Interactions:见文章InputSystem的Interactions作用及具体使用方法
Bind的属性窗口
Path:某个设备的输入信号,例如键盘A键、鼠标左键
Use in Control Scheme:关联解决方案,不关联解决方案,将自动从所有解决方案中查找对应的设备找到映射。
Interactions:见文章InputSystem的Interactions作用及具体使用方法
Processors
值处理,对输入值进行指定处理,如归一化、取反,限定范围等。Processors会根据Control Type不同出现不同的效果。
创建了InputActions配置文件,还需要一个PlayerInput组件来驱动。
Clamp:将输入值限制在[min,max]之间
Invert:将输入值取反
Normalize:如果最小值>=0,则将[min,max]范围内的输入值规格化为无符号规格化形式[0,1],如果最小值<0,则将输入值规格化为有符号规格化形式[-1,1]。当值是1DValue的时候,需要提供min、max。min和max分别代表输入值能够达到的最小值和最大值。根据提供的min和max对输入值作归一化处理,如滚轮极限值的绝对值为240,那么min为-240,max为240,zero为0。
Scale:输入值缩放
Deadzone:绝对值小于最小值的任何值为 0,绝对值大于最大值的任何值为 1 或 -1。
PlayerInput
Actions:InputActions配置文件
Default Scheme:一个默认的控制方案
Auto-Switch:运行过程中自动根据设备输入选择方案
Default Map:默认的映射集合
事件调用方式类型
Behaviour-设置事件调用方式类型
调用方式:
- SendMesssages-使用Unity自带的SendMessage消息机制,查找并回调当前游戏对象所挂脚本中的回调函数。对应Action的回调函数为On+”Action的名字“。
- BroadcastMessages-使用Unity自带的SendMessage消息机制,向当前游戏对象及层次结构中向下的所有游戏对象查找并回调所挂脚本中的回调函数。回调函数规则同SendMessages
- Invoke UnityEvents-采用UnityEvent配置每个Action的回调函数,允许你自定义回调函数方法名
- Invoke C Sharp Events-与UnityEvents类似,只是这些事件是 API 上可用的普通 C# 事件。您无法从检查器配置这些。相反,您必须在脚本中的手动为事件注册回调。
个人习惯使用Invoke UnityEvents,没有太多的规则束缚,方便自己随时配置修改。同时其性能也优于其他几种方式。
2022年6月8日 这一天是个压抑的一天,在满脑子胡思乱想下,完结了InputSystem的内容,到这里就要告一段落了。 今后在使用过程中如有新内容笔者会在此持续更新。内容如有错误,劳请各位勘误帮笔者加以改正,也欢迎各位在文章下方留有您的见解,万分感谢!
补充
一键创建资源信息类
如果开发者想要脱离PlayerInput组件的依赖,但又必须获取到ActionAsset资源。我们可以在此前创建好的ActionAsset资源的Inspector检视面板里勾选上Generate C# Class,设置路径、类名和命名空间后点击Apply即可自动生成一个脚本文件。
该脚本文件中包含了ActionAsset资源的所有信息并为其每一个ActionMap都配置了相应的接口和Wrapper类,这也就表示开发者可以在代码中直接引用该类而无需理会ActionAsset资源,同时也脱离了高度封装的PlayerInput组件。
END
InputSystem文章专辑:
InputSystem教程专辑
参考文章:
来源:麦瑞克博客
链接:https://www.playcreator.cn/archives/unity/unity_technologyshare/348/
本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议,转载请注明!
[…] InputSystem安装以及使用见文章 Unity-新InputSystem学习&该如何使用?|麦瑞克博客 […]