Unity 新版输入系统(Input System)

本文介绍了在Unity2019.4+版本中安装和使用新InputSystem的方法,包括安装步骤、监听按键按下和释放、创建ActionMap和Action,以及通过代码实现按键映射和长按功能。

前言

官方教程

注意
新的输入系统需要 Unity 2019.4+ 和 .NET 4 运行时。它不适用于 .NET 3.5 的项目。
教程版本:Unity 2021.3.26

1. 安装

1.1 打开 Package Manager

导航栏 -> Window -> Package Manager

![[Pasted image 20240325155507.png]]

1.2 安装 Input System

选择 Unity Registry 在列表中找到 Input System 点击Install安装

![[Pasted image 20240325155721.png]]

点击 Yes 启用新版 Input System 等待Unity重新启动

![[Pasted image 20240325161420.png]]

Unity 默认会同时启用旧版和新版输入系统,你可以在 Player settings 中(Edit -> Project Settings -> Player ->Active Input Handling 找到相应的设置。可以随时修改这里的设置,这样做依然会重启编辑器。

![[Pasted image 20240325162301.png]]

2. 入门指南

2.1 快速监听某个按键按下抬起操作

void Update()  
{  
    // 检查空格键是否在这个帧被按下  
    if (Keyboard.current.spaceKey.wasPressedThisFrame)  
    {        
	    Debug.Log("Space key was pressed");  
    }   
    // 检查空格键是否在这个帧被释放  
    if (Keyboard.current.spaceKey.wasReleasedThisFrame)  
    {        
	    Debug.Log("Space key was released");  
    }   
    // 检查左鼠标键是否在这个帧被按下  
    if (Mouse.current.leftButton.wasPressedThisFrame)  
    {        
	    Debug.Log("Left mouse button was pressed");  
    }  
    // 检查左鼠标键是否在这个帧被释放  
    if (Mouse.current.leftButton.wasReleasedThisFrame)  
    {        
	    Debug.Log("Left mouse button was released");  
    }
}

2.2 使用可视化编辑器来建立映射

Project -> Create -> Input Actions

![[Pasted image 20240325165116.png]]

新建 Input Actions 给其命名(名称无所谓),笔者命名为 Test Input Controls 完成后,选中该文件勾选 Generate C# Class点击 Apply 后 Unity 会为我们生成一个 Action 的包装类,方便后续在代码中引用。

![[Pasted image 20240325173907.png]]

Action Map
可以理解为一个组织和管理输入动作的一种方式。通过将相关的输入动作放在同一个Action Map中,可以更好地管理输入逻辑。例如,可以将所有与玩家移动相关的输入动作放在一个叫做"Movement"的Action Map中。

Action
一个具体的输入动作,比如按键按下、摇杆移动等。

生成结束点击 Edit asset 创建第一个 Action Map 并将其命名为 Player 并将 Actions 列表生成的 Action 重命名为 Fire

![[Pasted image 20240325181359.png]]

选中 < No Binding >Fire Action 映射对应的按键(按键可以自定义,笔者映射的按键为键盘的 K 键)

![[Pasted image 20240325181748.png]]

也可以绑定多个按键对应不同的操作设备,笔者映射的第二个按键为鼠标左键

![[Pasted image 20240326094550.png]]

![[Pasted image 20240326180304.png]]
完成上述操作后点击 Save Asset 保存当前映射表,这样做可以绑定多个物理输入得到的输入值也只会影响同引用的 Action 对象。

![[Pasted image 20240326180326.png]]

2.3 通过代码监听映射表中的按键

创建测试脚本 TestInputSystem (命名可随意),我们需要使用之前的 TestInputControls ,通过监听 startedcanceled 实现按键按下抬起操作。具体可参考下述代码

// 输入控制类的实例  
private TestInputControls InputControls;  
  
void OnEnable()  
{  
    InputControls = new TestInputControls(); // 创建输入控制实例  
    InputControls.Player.Fire.started += OnFireDown; // 注册开火开始动作的回调  
    InputControls.Player.Fire.canceled += OnFireUp; // 注册开火结束动作的回调  
    InputControls.Enable(); // 启用输入控制  
}  
  
//当开火动作被触发时调用此方法。  
private void OnFireDown(InputAction.CallbackContext Obj)  
{  
    Debug.Log($"Fire Down | KeyName:{Obj.control.name}"); // 输出"Fire Down"到控制台 
}
  
//当开火动作释放时调用此方法。  
private void OnFireUp(InputAction.CallbackContext Obj)  
{  
    Debug.Log($"Fire Up | KeyName:{Obj.control.name}"); // 输出"Fire Up"到控制台 
}
  
//主要用于移除输入动作的回调函数,并禁用输入控制。  
private void OnDisable()  
{  
    InputControls.Player.Fire.started -= OnFireDown; // 移除开火开始事件的监听器  
    InputControls.Player.Fire.canceled -= OnFireUp; // 移除开火结束事件的监听器  
    InputControls.Disable(); // 禁用输入控制  
}

测试效果

可以看到,我们使用一套代码就可以同时监听键盘和鼠标的输入

![[Pasted image 20240326181829.png]]

按下抬起有了,要想实现长按也很简单。选中 TestInputControls 点击 Edit asset
Action Properties 一栏点击 Interactions 后方的+号添加 Hold

Hold:按下并按住至少设定的持续时间(默认为defaultHoldTime),则执行动作。(长按执行操作)
MultiTap:需要多次轻击(在tapTime内按下并释放),每次轻击之间的间隔不超过tapDelay秒(双击或多击)
Press:根据按钮的按下和释放顺序来触发特定的操作(例如:在按下按钮后执行某个动作或在释放按钮时执行某个操作)
SlowTap:按下并按住控件一段时间后释放时执行操作(长按释放后执行操作)
Tap:按下并按住小段时间内释放执行操作(点击)

![[Pasted image 20240326140155.png]]

添加完 Hold 后,我们看一下它的两个变量。如何默认值不能满足你的需求,取消勾选 Default 可自定义变量值。修改 Hold Time 变量一般即可满足需求

Press Point:按下按键这个阈值才能被认为是按下(笔者理解的是按压力度)
Hold Time:按下并按住按键保持的时间(以秒为单位)。

![[Pasted image 20240326142645.png]]

还是之前的代码在此基础上增加了长按监听的代码,具体参考下述代码

// 输入控制类的实例  
private TestInputControls InputControls;  
  
void OnEnable()  
{  
    InputControls = new TestInputControls(); // 创建输入控制实例  
    InputControls.Player.Fire.started += OnFireDown; // 注册开火开始动作的回调  
    InputControls.Player.Fire.performed  += OnLongPress; // 注册长按动作的回调  
    InputControls.Player.Fire.canceled += OnFireUp; // 注册开火结束动作的回调  
    InputControls.Enable(); // 启用输入控制  
}  
  
//当开火动作被触发时调用此方法。  
private void OnFireDown(InputAction.CallbackContext Obj)  
{  
    Debug.Log($"Fire Down | KeyName:{Obj.control.name}"); // 输出"Fire Down"到控制台 
}  
  
//当开火动作持续时调用的方法。  
private void OnLongPress(InputAction.CallbackContext Obj)  
{  
    Debug.Log($"Fire Long Press | KeyName:{Obj.control.name},持续时间{Obj.duration}"); // 输出动作持续时间  
}  
  
//当开火动作释放时调用此方法。  
private void OnFireUp(InputAction.CallbackContext Obj)  
{  
    Debug.Log($"Fire Up | KeyName:{Obj.control.name}"); // 输出"Fire Up"到控制台  
}  
  
//主要用于移除输入动作的回调函数,并禁用输入控制。  
private void OnDisable()  
{  
    InputControls.Player.Fire.started -= OnFireDown; // 移除开火开始事件的监听器  
    InputControls.Player.Fire.performed  -= OnLongPress; // 移除长按事件的监听器  
    InputControls.Player.Fire.canceled -= OnFireUp; // 移除开火结束事件的监听器  
    InputControls.Disable(); // 禁用输入控制  
}

经过上述步骤,我们学习到了新版 InputSystem 中的三个最基本的按键触发。

<think>好的,用户现在想了解Unity的新输入系统Input System的按键事件处理。我之前已经回答过他们关于Cesium for Unity的问题,现在他们转向了输入系统。我需要先确定用户的使用场景和需求。可能他们在开发游戏或交互式应用,需要处理玩家输入,比如键盘、手柄等。 用户提到的是“按键事件”,所以重点应该是如何检测和处理按键的按下、按住、释放等事件。他们可能之前用过旧的Input Manager,现在想迁移到新的Input System,或者刚开始学习,想了解最佳实践。 首先,我要介绍Input System的基本概念,比如Actions和Action Maps,因为这是新系统的核心。然后,需要分步骤说明如何设置Input System,创建输入动作,以及编写代码处理事件。示例代码会帮助用户理解实现方法。 另外,用户可能需要知道不同的事件类型(started, performed, canceled)之间的区别,以及如何区分按键类型,比如单个按键、组合键。性能优化和常见问题也是需要考虑的部分,比如输入设备类型的处理和多玩家输入的情况。 要确保回答结构清晰,步骤明确,代码示例正确,并且用中文通俗易懂地解释概念。同时,提醒用户注意Package Manager中安装Input System,以及旧系统的兼容性问题。可能还需要提到输入调试工具,帮助用户测试和验证输入事件。 最后,总结一下使用Input System的好处,比如更灵活、支持更多设备、事件驱动等,让用户明白为什么值得升级到新系统。</think>在Unity中使用**Input System**处理按键事件,相比旧版输入系统更加灵活且支持跨平台。以下是详细实现流程及核心代码示例: --- ### **1. 安装与基础配置** - **安装Input System包** 通过Unity Package Manager安装`Input System`(需启用**Preview Packages**) ```csharp // 旧输入系统需关闭兼容性: #if ENABLE_LEGACY_INPUT_MANAGER #error 需在Player Settings中关闭旧输入系统 #endif ``` - **创建Input Actions资产** 右键菜单选择 `Create > Input Actions`,命名为`PlayerControls` --- ### **2. 定义按键事件** **Step 1 - 编辑Input Actions** 打开`PlayerControls.inputactions`,按结构创建: 1. **Action Maps**: `Gameplay` (分类不同操作场景) 2. **Actions**: - `Move` (2D向量,绑定WASD/方向键) - `Jump` (按钮类型,绑定空格键) - `Attack` (按钮类型,绑定鼠标左键) **Step 2 - 生成C#封装类** 在资产属性面板勾选`Generate C# Class`,生成`PlayerControls.cs` --- ### **3. 按键事件监听实现** #### **方式1:直接读取输入状态** ```csharp using UnityEngine; using UnityEngine.InputSystem; public class DirectInput : MonoBehaviour { private PlayerControls _controls; void Awake() { _controls = new PlayerControls(); _controls.Gameplay.Enable(); } void Update() { // 持续获取移动输入 Vector2 moveInput = _controls.Gameplay.Move.ReadValue<Vector2>(); // 检测单次跳跃按键 if(_controls.Gameplay.Jump.triggered) { Jump(); } } } ``` #### **方式2:事件回调(推荐)** ```csharp public class EventDrivenInput : MonoBehaviour { private PlayerControls _controls; void OnEnable() { _controls = new PlayerControls(); _controls.Gameplay.Jump.performed += OnJump; _controls.Gameplay.Attack.started += OnAttackStart; _controls.Gameplay.Attack.canceled += OnAttackEnd; _controls.Enable(); } void OnDisable() { _controls.Disable(); _controls.Gameplay.Jump.performed -= OnJump; } private void OnJump(InputAction.CallbackContext context) { // 获取按压强度(适用于模拟摇杆) float pressure = context.ReadValue<float>(); Debug.Log($"跳跃触发,压力值:{pressure}"); } private void OnAttackStart(InputAction.CallbackContext ctx) { Debug.Log("攻击键按下"); } private void OnAttackEnd(InputAction.CallbackContext ctx) { Debug.Log("攻击键释放,持续时长:" + ctx.duration); } } ``` --- ### **4. 高级功能实现** #### **组合键检测** ```csharp // 在Input Actions中创建复合绑定 // 修改`Attack`的绑定路径为: // "<Keyboard>/ctrl + <Mouse>/leftButton" // 代码检测: _controls.Gameplay.Attack.performed += ctx => { if(Keyboard.current.ctrlKey.isPressed) { Debug.Log("Ctrl+左键组合攻击"); } }; ``` #### **设备类型区分** ```csharp void HandleDeviceType() { InputSystem.onActionChange += (obj, change) => { if(change == InputActionChange.ActionPerformed) { var action = (InputAction)obj; string deviceType = action.activeControl.device.displayName; Debug.Log($"当前输入设备:{deviceType}"); } }; } ``` --- ### **5. 输入调试技巧** 1. 打开调试窗口:`Window > Analysis > Input Debugger` 2. 实时查看设备输入信号 3. 使用**Input Action Triggers**组件可视化测试事件 --- ### **关键概念对比** | 事件类型 | 触发时机 | 典型用途 | |---------------|-----------------------------------|------------------------| | `.started` | 按键最初按下瞬间 | 开始蓄力、音效触发 | | `.performed` | 操作达到阈值(如摇杆超过死区) | 移动确认、技能释放 | | `.canceled` | 操作结束(按键释放或离开阈值) | 停止动作、状态重置 | --- ### **常见问题解决** 1. **输入无响应** - 检查`_controls.Enable()`是否被调用 - 确认Action Maps的当前激活状态 2. **多玩家输入处理** ```csharp // 使用PlayerInput组件分割设备 var player1 = PlayerInput.Instantiate(prefab, controlScheme: "Keyboard"); var player2 = PlayerInput.Instantiate(prefab, controlScheme: "Gamepad"); ``` 3. **移动端适配** 在`Player Input`组件中设置`Default Control Scheme`为`Touch` --- 通过Input System的事件驱动架构,开发者可以更高效地处理复杂输入逻辑。建议结合[官方交互文档](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.3/manual/Interactions.html)实现连击、蓄力等高级交互功能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天喝水了嘛.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值