概述
Unity的新输入系统(New Input System)是一个更加灵活和可扩展的输入解决方案,它提供了比传统的UnityEngine.Input
更多的功能和改进。
安装和激活
要安装新输入系统,你需要打开Unity的包管理器(菜单:Window > Package Manager),选择Input System包进行安装。安装完成后确认窗口,这将导致编辑器重启且关闭旧输入系统(InputManager)的使用。
如果希望同时使用两种输入系统,可以在(菜单:Edit > Project Settings > Player)中找到Active Input Handling属性,将属性值改为Both,就可以同时开启两种输入系统。
新输入系统需要Unity 2019.4或更高版本,并且需要.NET 4运行时。它不适用于使用旧.NET 3.5运行时的项目。
简单原理介绍
新输入系统基于事件,将输入设备和动作逻辑分离,并通过配置映射来处理输入信息。这使得它在多设备和多平台输入处理时更加强大和灵活。新输入系统设计时考虑了多设备支持,包括键盘、鼠标、游戏手柄、触摸、VR和XR等。这使得它在处理各种输入设备时更加高效和一致。
假设玩家A使用Gamepad时,按下Gamepad上的X键,通过InputSystem资源配置文件中对设备输入和玩家自定义的多种输入方式进行匹配,最终通过相关方法调用,可在脚本中获取所需要的值。
配置文件基本介绍
在安装NewInputSystem后,可以在Project窗口中创建InputActions资源配置文件进行;也可以给场景物体先挂载一个PlayerInput组件(配置文件创建完后可删除),在组件中创建InputActions资源配置文件,通过PlayerInput组件创建的InputActions会配置好一些基本的按键映射,可供直接使用(资源配置文件放置在自己创建的配置文件夹中)。
InputActions资源配置文件分为三个部分
第一区域
Action Maps是用于设置不同使用场景的映射表,项目中对于玩家角色的操作,UI的操作,汽车驾驶操作等等场景的相同按键进行不同的操作配置。新增新的映射表直接点击右上角的+号。
第二区域
Actions 对不同操作进行配置。例如玩家的操作可以有移动,跳跃,射击等等,就可以通过右上角的+号新增新的动作映射。在动作下还可以配置不同设备对于当前动作的控制映射。
第三区域
Action Properties 是对Actions中各类属性的设置内容。
例如:现在我需要为当前Player映射表新增一个新的动作Jump。
1.点击 + 新建新的操作(Action)并重命名,设置操作输出的值类型。Action Type选择Value,Controller Type则可以进行输出值类型选择。Button则是布尔类型,Vector2则是二维数组类型,以此类推。通常按键选择Botton(也可以直接在ActionType中直接选择Button),摇杆或者用于移动控制则是使用Vector2。
2.点击 + ,选择Add Binding,新建新的控制映射。
3.选定当前按键映射,在Path属性下选择当前设备中连接的所有输入设备的按钮,随后选择需要的按钮。也可以通过监听的方式直接获取需要的设备按键,点击红框中的Listen,当前Listen显示高亮(不懂什么Bug被遮挡了)后再在输入设备上按下需要的按键。
4.选定当前按键映射进行约束设置,也就是为当前按钮设定一个类型,减少出现错误识别的问题。
5.点击Save Asset或者勾选Auto Save对配置文件InputActions进行保存。(这很重要!!!)
脚本中使用NewInputSystem的工作流
直接使用控制器控制
csharp
using UnityEngine;
using UnityEngine.InputSystem;
public class InputByDecive : MonoBehaviour
{
//物体移动速度
public float speed;
void Update()
{
//获取手柄控制器对象
var gamePad = Gamepad.current;
if (gamePad != null)
{
//读取手柄控制器左摇杆的输入值
Vector2 moveInput = gamePad.leftStick.ReadValue();
{
if (moveInput != Vector2.zero)
{
//位移控制
moveInput = moveInput.normalized;
var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
transform.Translate(moveDirection * speed * Time.deltaTime);
}
}
}
}
}
将脚本挂载在物体上,对物体(红色小球)进行移动控制。
这通常是设置一些响应输入的代码的最快方法,但它是最不灵活的。无法有效的管理所有的输入,到开发后期输入增多代码混乱。
直接操作InputAction(按键映射对象)
InputAction
是新输入系统中的一个关键类,代表一种动作逻辑,可以绑定到多个物理输入上。每个动作逻辑在任何时刻都有一个状态阶段,例如Started, Performed, Canceled等,你可以根据这些阶段来响应输入。
csharp
using UnityEngine;
using UnityEngine.InputSystem;
public class InputByInputAction : MonoBehaviour
{
//InputAction动作对象引用
public InputAction moveAction;
public float speed;
void Start()
{
//第一种
//moveAction.performed += OnMove1;
}
void Update()
{
//第二种
OnMove2();
}
//第一种通过事件绑定的方式事项控制
//事件回调函数
private void OnMove1(InputAction.CallbackContext context)
{
通过回调获取输入值
Vector2 moveInput = context.ReadValue<Vector2>();
{
if (moveInput != Vector2.zero)
{
moveInput = moveInput.normalized;
var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
transform.Translate(moveDirection * speed * Time.deltaTime);
}
}
}
//第二种直接获取输入值
private void OnMove2()
{
if (moveAction != null)
{
Vector2 moveInput = moveAction.ReadValue<Vector2>();
{
if (moveInput != Vector2.zero)
{
moveInput = moveInput.normalized;
var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
transform.Translate(moveDirection * speed * Time.deltaTime);
}
}
}
}
//InputAction在使用前需要开启功能,不然接收不到输入
void OnEnable()
{
moveAction.Enable();
}
void OnDisable()
{
moveAction.Disable();
}
}
将脚本挂载在物体上,在Inspector窗口中创建新的InputAction对象并配置按键后,对物体(红色小球)进行移动控制。
使用 InputActions 还可以更轻松地实现输入控制,以允许用户在运行时重新映射新的按键输入。直接读取设备状态更灵活,但不如使用InputActionAssets灵活。
操作InputActionAssets按键映射表
InputActionAssets 这是一种资源文件,用于存储动作绑定关系,扩展名为.InputActions,数据格式为JSON。
csharp
using UnityEngine;
using UnityEngine.InputSystem;
public class InputByInputActionAsset : MonoBehaviour
{
//InputActionAsset资源配置文件引用
public InputActionAsset inputActions;
//在当前InputActionAsset中需要使用的InputAction动作对象
private InputAction moveAction;
public float speed;
void Start()
{
if (inputActions != null)
{
//从资源配置文件中获取InputAction
moveAction = inputActions.FindActionMap("Player").FindAction("Move");
}
if (moveAction != null)
{
//方法1
moveAction.performed += Move1;
}
}
void Update()
{
//方法2
// Move2();
}
//第一种通过事件绑定的方式事项控制
//事件回调函数
private void Move1(InputAction.CallbackContext context)
{
Vector2 moveInput = context.ReadValue<Vector2>();
{
if (moveInput != Vector2.zero)
{
moveInput = moveInput.normalized;
var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
transform.Translate(moveDirection * speed * Time.deltaTime);
}
}
}
//第二种直接获取输入值
private void Move2()
{
if (moveAction != null)
{
Vector2 moveInput = moveAction.ReadValue<Vector2>();
{
Debug.Log("Move:" + moveInput);
if (moveInput != Vector2.zero)
{
moveInput = moveInput.normalized;
var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
transform.Translate(moveDirection * speed * Time.deltaTime);
}
}
}
}
//InputActionAssets和InputAction在使用前都需要开启功能,不然接收不到输入
void OnEnable()
{
if (inputActions != null)
{
inputActions.FindActionMap("Player").Enable();
if (moveAction != null)
{
moveAction.Enable();
}
}
}
void OnDisable()
{
if (inputActions != null)
{
inputActions.FindActionMap("Player").Disable();
if (moveAction != null)
{
moveAction.Disable();
}
}
}
}
将脚本挂载在物体上,在Inspector窗口中配置创建的InputActions资源配置文件,对物体(红色小球)进行移动控制。
InputActions非常有用,因为它意味着所有操作定义都存储为单个资源文件中,可以让脚本和预制件分开。这可以使输入控制文件的管理更简单。
使用PlayerInput组件
PlayerInput组件将输入事件高度封装,只需要在组件中对需要调用的方法进行事件配置,就可以实现物体的控制操作。
ini
using UnityEngine;
using UnityEngine.InputSystem;
public class InputByPlayerInput : MonoBehaviour
{
public float speed=5f;
//方法需要传入InputAction.CallbackContext,满足时间绑定的条件
public void OnMove(InputAction.CallbackContext context)
{
Vector2 moveInput = context.ReadValue<Vector2>();
{
if (moveInput != Vector2.zero)
{
moveInput = moveInput.normalized;
var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
transform.Translate(moveDirection * speed * Time.deltaTime);
}
}
}
}
1.将脚本挂载在物体上
2.为对象新增PlayerInput组件
2.1 在Inspector窗口中的Actions属性下配置创建的InputActions资源配置文件或者选择创建好的资源配置文件
2.2 在Behavior属性中选择Invoke Unity Events,也就可以读取到InputActions资源配置文件中Actions下设置好的动���的事件对象。
2.3在Events -> Player属性中找到要设置的动作事件,点击 +
2.4将脚本挂载在当前属性中,
2.5在左侧方法中选择当前到本的相关方法。
3.对物体(红色小球)进行移动控制。
与前面的工作流代码示例相比,您可以看到此方法需要更少的代码,因为您不必在自己的脚本中引用 Actions 资源配置文件或设置事件处理程序方法。但是,它确实需要在编辑器中进行更多设置,并且可能会使调试更加困难,因为操作和代码之间的连接不是硬编码的。
与描述的其他工作流一样,在灵活性、简单性和实现速度之间需要权衡。
总结
使用InputSystem可以极大的提高开发效率,让输入控制的管理变得更简单。