Unity 新的输入系统Input System(一)

本文详细介绍Unity新输入系统InputSystem的安装、配置及使用方法。通过对比传统输入方式,展示InputSystem如何简化多设备输入处理,实现更灵活的输入绑定。并解析InputAction的高级应用,包括复合绑定、交互模式及事件通知机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看见Unity出了新的输入系统Input System,本着喜新厌旧的原则,就让我们来学习学习这个新系统。

官方文档:https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Installation.html

 

安装

运行环境:Unity 2019.1+ 和 .NET 4 runtime

官方的文档中已经讲得很详细了,我英语这么差都能看懂,大家肯定莫得问题。

简单来说就是在Package Manager中安装Input System,然后在Project Settings中的Player设置里将Active Input Handling设置为Input System即可。

设置好后运行工程,会发现之前的UGUI的界面无法响应点击事件,我们需要将默认场景中的EventSystem中的Standalone Input Module变更为新的Input System UI Input Module组件。

 

简单入门

环境配置好后,我们就可以在脚本中直接通过获取输入设备来获取输入,比如

var gamepad = Gamepad.current;//手柄
var keyboard = Keyboard.current;//键盘
var mouse = Mouse.current;//鼠标
var pointer = Pointer.current;//指针

if (gamepad != null)
{
    Debug.Log(gamepad.leftStick.ReadValue());//手柄遥感的偏移
    if (gamepad.bButton.wasPressedThisFrame)
        Debug.Log("按下B键");
}
if (keyboard != null)
{
    //执行顺序 isPressed = false -> 按下:wasPressedThisFrame = true -> 中途:isPressed = true -> 松开:wasReleasedThisFrame = true -> isPressed = false
    if (keyboard.wKey.wasPressedThisFrame)
        Debug.Log("w键按下(一直按住w键的话,也只执行一次)");
    if (keyboard.wKey.wasReleasedThisFrame)
        Debug.Log("w键松开");
    Debug.Log("是否按住w键:" + keyboard.wKey.isPressed);
}
if (mouse != null)
{
    Debug.Log(mouse.scroll.ReadValue());//滚轮的滚动值,向前滚Y的值为正,向后滚为负

    if (mouse.leftButton.wasPressedThisFrame)
        Debug.Log("按鼠标左键");
    if (mouse.rightButton.wasPressedThisFrame)
        Debug.Log("按鼠标右键");
    if (mouse.middleButton.wasPressedThisFrame)
        Debug.Log("按滚轮键");
}
if (pointer != null)
{
    Debug.Log(pointer.delta.ReadValue());//与上一帧的偏移
    Debug.Log(pointer.position.ReadValue());//在空间中的坐标
}

更加详细的介绍我们可以在文档中 支持的输入设备 处查阅

 

通过上面的方法,我们会发现加入我们有些事件可以通过多种输入来触发,比如射击,可以通过鼠标左键、点击屏幕、按键盘,这样就会很麻烦,需要获取很多的设备去设置。或者我们想在后期添加新的输入来控制,比如使用遥感来射击等等,也会很不方便。为了解决这种问题,我们还可以通过Input Action来间接的获取输入。

首先我们给一个GameObject添加PlayerInput组件,每个PlayerInput组件即代表一个玩家。添加好组件后,如果我们要接受到输入,还需要创建Action。我们可以点击组件上的Create Actions按钮来创建,会弹出一个对话框,来选择存放生成的.inputactions文件路径。创建成功后就会弹出下面这样的编辑界面,先保持默认即可。

通过这个界面,我们可以看出,假如我们有个角色移动的操作要处理,即图中的Move Action,看Move的内部可以知道,触发该Action的方式有手柄的左遥感,或者键盘的wasd按键等等。这样相比之前的直接获取输入设备而言可以更好的控制触发条件,并且后期添加新的设备触发条件的话,只需要更改这个Asset文件即可。

我们先来简单的看下里面的一些参数。

右键一个Action我们可以看见有如下这些选项,都可以用于为Action添加绑定。

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

 

Action Type

Value默认,主要用于状态连续更改的输入,例如鼠标的移动,手柄的遥感。如果有多个设备绑定这个Action,只会发送其中一个设备(最受控制的)的输入
Button用于每次按下时触发的Action
Pass-Through和Value一样,区别在于如果有多个设备绑定这个Action,会发送所有设备的输入

Interactions

Interaction(交互)主要用于一些特殊的输入模式,例如其中的Hold模式,要求控件至少保持的时间。

你可以在Action或者Binding下设置它,如果在Action下设置,那么该Action下的每个Binding都会在达成条件下触发这个Interaction。如果在同一个Action或Binding上绑定多个Interaction,则会按照其顺序进行检测。

Unity自带一个可以使用的基本交互(default Interaction),如果用户没有自定义交互的话,系统默认会使用default Interaction。

下面是几种Interaction介绍:

Default:当Action Type为Value或Button时,当输入设备响应会调用started回调(例如按钮按下,或者鼠标开始拖动),当设备响应中时会调用performed回调(在started后触发,调用一次。若为Value的话,当值发生变化会再次触发,例如遥感,按住之后每次偏移位置都会触发一次),当输入设备结束响应会调用canceled回调(例如按钮松开,或者鼠标停止拖动)。当Action Type为PassThrough的时候,只会调用performed回调。

Press:可以实现类似按钮的操作

Trigger Behavior 
Press Only按下的时候触发started和performed。不触发canceled
Release Only按下的时候触发started,松开的时候触发performed。不触发canceled
Press And Release按下的时候触发started和performed,松开的时候会再次触发started和performed。不触发canceled

Press Point:在Input System中,每个按钮都有对应的浮点值,例如普通的按钮,将会在0(未按下)和1(按下)之间。因此我们可以利用这个值(Press Point)来进行区分,当大于等于这个值则认为按钮按下了。

Hold:适用于需要输入设备保持一段时间的操作。当按钮按下会触发started,若在松开按钮前,按住时间大于等于Hold Time则会触发performed(时间一到就触发),否则触发canceled。

Tap:和Hold相反,需要在一段时间内按下松开来触发。当按钮按下会触发started,若在Max Tap Duriation时间内(小于)松开按钮,触发performed,否则触发canceled。

SlowTap:类似Hold,但是它在按住时间大于等于Max Tap Duriation的时候,并不会立刻触发performed,而是会在松开的时候才触发performed

MultiTap:用作于多次点击,例如双击或者三连击。Tap Count为点击次数,Max Tap Spacing为每次点击之间的间隔(默认值为 2 * Max Tap Duration)。Max Tap Duration为每次点击的持续时间,即按下和松开按钮的这段时间。当每次点击时间小于Max Tap Duration,且点击间隔时间小于Max Tap Spacing,点击Tap Count次,触发performed。

 

.inputactions文件的介绍大致如上,接着我们要为创建好的Action设置响应,如图:

通过Player Input组件的Behavior属性,来设置Player Input组件通知游戏代码的方式。

Send Messages通过在Player Input所属的GameObject上,利用GameObject.SendMessage()来通知
Broadcast Messages通过在Player Input所属的GameObject上,利用GameObject.BroadcastMessage()来通知
Invoke Unity Events为每个消息使用单独的UnityEvent,选中的时候会在下面显示Event属性来让我们设置

Invoke C Sharp Events

在脚本中注册事件回调,可用的事件有

onActionTriggered(玩家所以操作的事件集合)

onDeviceLose(设备丢失)

onDeviceRegaine(设备恢复)

除了Action的通知外,Player Input还会发送下面两个常规通知

Device Lost Event玩家丢失了输入设备,例如设备没电了,或者断开连接等
Device Regained Event玩家的设备恢复正常使用

 

我们这里先选择Invoke Unity Events的方式来通知事件,在下面的Events折叠栏中,我们可以去关联脚本中的方法。每个事件的方法都需要一个InputAction.CallbackContext参数,我们可以从中获取一些事件信息。

public void OnMove(InputAction.CallbackContext context)
{
    Vector2 move = context.ReadValue<Vector2>();
}

 

大致了解了之后,我们再来看看几个官方的Demo,从Package Manager中导入demo

我们先来看看Simple Demo,打开SimpleDemo_UsingPlayerInput.unity运行,我们可以用wasd来移动,鼠标指针来控制朝向,点击鼠标左键来发射(其他几个例子的效果也是一样的,实现的方式不同)。

点击Player查看其Player Input组件,实现的方法就和我们上面所介绍的一样,如果我们想要添加一个方式,利用Q键来发射。只需要在Actions的编辑界面中,fire出点击右边的小加号选择Add Binding,然后关联上KeyBoard的Q键即可。

大家自行理解下即可,这样就是一个最简单的利用新的Input System的例子。

其他几个demo的内容和后续的内容详解后续继续补充。

 

<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)实现连击、蓄力等高级交互功能。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值