Unity 新输入系统InputSystem(基本操作)

一、新输入系统(Input System)核心定位

Unity 新输入系统是 Unity 官方推出的、替代旧InputManager的新一代输入管理工具,核心优势是跨平台适配性强 (PC / 手机 / 手柄 / VR 等)、逻辑结构化 (告别零散的Input.GetKey)、可可视化配置。

二、核心概念(新手必懂)

先理清几个基础概念,避免上手混乱:

  1. Input Actions(输入动作):这是核心!把 "输入行为" 和 "物理输入设备" 解耦。比如你游戏里的 "发射子弹""暂停游戏""Ctrl + 发射" 都是独立的 Input Action,不用关心是鼠标左键、手柄按键还是触屏触发。
  2. Input Action Map (输入动作映射):对 Input Action 分组管理。比如给打气球游戏分两组:
    • GamePlay:包含 "发射子弹""暂停游戏""Ctrl 发射定位" 等核心操作;
    • UI:包含 "点击按钮" 等 UI 操作。
  3. Binding (绑定):把 Input Action 和具体的物理输入绑定。比如:
    • "发射子弹" 绑定到「鼠标左键」;
    • "Ctrl 发射定位" 绑定到「Left Ctrl + 鼠标左键」;
    • "暂停游戏" 绑定到「ESC 键」。
  4. Input Device(输入设备):自动识别鼠标、键盘、手柄等设备,无需手动判断设备类型。
  5. Player Input :挂载在玩家对象上的组件,用于关联 Input Action Map,并通过事件驱动(如OnActionTriggered)响应输入,是新手最易上手的方式。

三、核心差异总结

  1. 设计逻辑

    • 旧系统:「设备绑定」,直接写代码检测 "鼠标左键""ESC 键" 等具体按键,比如你要实现 Ctrl + 鼠标左键,需手动写代码判断两个按键是否同时按下;
    • 新系统:「行为绑定」,先定义 "发射子弹""暂停游戏" 等行为,再可视化绑定到任意按键 / 组合键(比如把 "Ctrl + 左键" 直接绑给 "定位发射" 行为),无需手动拼接判断。
  2. 使用方式

    • 旧系统:纯代码,必须在 Update 里逐帧检测按键(比如每一帧查鼠标左键是否按下),逻辑零散;
    • 新系统:可视化配置 + 事件驱动,按键触发时自动回调方法(比如 "发射子弹" 行为触发时,直接执行发射逻辑),无需逐帧检测,代码更整洁。
  3. 扩展适配

    • 旧系统:适配手柄 / 触屏等新设备,需重新写大量适配代码;
    • 新系统:同一行为可绑定多设备(比如 "发射" 既绑鼠标左键,也绑手柄 A 键),自动适配,无额外代码。
  4. 调试与维护

    • 旧系统:无专门调试工具,改按键需改代码;
    • 新系统:内置调试工具,改按键只需在面板上重新绑定,无需改代码,维护更方便。

四、 基础配置流程(新手步骤)

  1. 安装:Package Manager 中搜索 "Input System" 安装(安装后需重启 Unity);

第一步:窗口->包管理器

第二步:包管理器->输入Input System->下载

第三步:编辑->项目设置->玩家->点击新输入系统

2.创建 Input Actions 资源:右键->创建Actions文件夹->右键->Input Actions(只有下载了Input Action才会出现),可起名为PlayerActions->双击PlayerActions

配置PlayerActions(建议勾上Auto-Save时时保存):

3.编辑 Input Actions:

(1)新建 Action Map:命名为Play和UI

(2)在Play下添加 Action:1,Move 2,Look 3,Jump(基本操作)

1.Move:Actions Tap选值 Control Tap 选Vector 2(点击Move可直接选Add Up\Left\Right Composite(帮你自动生成WSAD))

然后分别在WSAD的Path里选择WSAD键(点击WSAD时按回车或右键,点击左键没用)

2.Look: Actions Tap选值 Control Tap 选Vector 2(同上操作选择Delta [mouse]

3.Jump:Actions Tap 选按钮 (同上操作选择 Space [Keyboard])

补充:如果想添加手柄,可在1,Move 2,Look 3,Jump分别添加这三个(根据实际手柄来添加):

(3)应用:点击Cenerate c# Class按钮->点击应用

我遇到的问题:编译错误(Unity Input System自动生成的代码,文件名和类名冲突了)

解决办法:我重命名了PlayerActions,改为PlayerAction,就没问题了。(自动生成的代码中 有PlayerActions,取一个不是这个的名字就可以)

4.给玩家对象挂载Player Input组件:

(1)在Player上添加Player Input组件

(2)把PlayerAction托到Actions即可

补充:如果不想自己配置,可以直接点击Create Actions会自动生成(自己改一改,删一删就 可以了)

就此,unity的基本配置就完成了。

五、在脚本中使用

步骤 1:引入新输入系统命名空间(基础前提)
cs 复制代码
using UnityEngine;
using UnityEngine.InputSystem;  

作用: 必须引入该命名空间,才能识别新输入系统的所有类(如PlayerInputInputActionInputAction.CallbackContext等),否则会报 "类型未定义" 错误;

步骤 2:声明新输入系统核心变量(存储引用)
cs 复制代码
// 核心:PlayerInput组件引用(挂载在玩家对象上的输入核心组件)
private PlayerInput playerInput;

// 存储单个输入动作的引用(与Input Actions中配置的Move/Look/Jump一一对应)
private InputAction moveAction;
private InputAction lookAction;
private InputAction jumpAction;

// 存储输入动作的数值(Vector2类型,适配二维输入:WASD/鼠标/摇杆)
private Vector2 moveInput;
private Vector2 mouseInput;
  • 变量作用说明
    1. PlayerInput:新输入系统的核心组件,是脚本与「可视化配置的 Input Actions」之间的桥梁,所有输入动作都通过它获取;
    2. InputAction:表示单个输入动作(如 "移动""视角""跳跃"),是新输入系统中 "行为驱动" 的核心载体,与具体按键 / 设备解耦;
    3. Vector2类型的moveInput/mouseInput:存储输入动作的数值结果 (如 Move 动作返回 WASD 的「左右 / 上下」值,Look 动作返回鼠标的「X/Y 移动增量」),范围通常为-1~1
  • 编写要点:根据游戏需求,声明需要的输入动作和输入值变量,命名与 Input Actions 中配置的动作名一致(方便识别)。
步骤 3:Awake 中获取新输入系统核心引用(初始化)
cs 复制代码
private void Awake()
{
    // 1. 获取玩家对象上挂载的PlayerInput组件(必须提前在编辑器挂载并配置)
    playerInput = GetComponent<PlayerInput>();

    // 2. 通过PlayerInput.actions获取所有配置的输入动作集合
    var actions = playerInput.actions;

    // 3. 根据「Input Actions中配置的动作名」,获取单个输入动作的引用
    // 注意:中括号内的字符串必须与Input Actions里的动作名完全一致(大小写敏感)
    moveAction = actions["Move"];
    lookAction = actions["Look"];
    jumpAction = actions["Jump"];
    
}
  • 核心逻辑解析
    1. playerInput = GetComponent<PlayerInput>():从当前玩家对象(People 脚本挂载的对象)上,获取提前在Inspector 面板手动挂载PlayerInput组件;
    2. playerInput.actions:返回该 PlayerInput 组件关联的Input Actions 资源中,所有已配置的动作集合(包含 GamePlay 等 Action Map 下的所有 InputAction);
    3. actions["Move"]:通过动作名索引 ,从动作集合中获取指定的单个 InputAction,赋值给脚本中的moveAction变量,后续通过该变量读取输入 / 绑定事件;
  • 编写前提 :必须先在 Unity 编辑器完成 2 个操作(否则此步骤会报空引用):✅ 给玩家对象挂载 PlayerInput 组件 ;✅ 在 PlayerInput 组件的Actions 属性 中,拖入提前创建并配置好的Input Actions资源(已配置 Move/Look/Jump 动作)。
步骤 4:OnEnable 中绑定输入事件(事件驱动型输入)
cs 复制代码
private void OnEnable()
{
    // 注册Jump动作的「performed」事件回调:当Jump动作触发时(如按空格),执行OnJumpPerformed方法
    jumpAction.performed += OnJumpPerformed;
}
  • 新输入系统核心事件InputAction提供 3 个核心事件,适配不同输入阶段,这里使用performed(最常用):
    1. started:输入开始触发时调用(如按下按键的瞬间);
    2. performed:输入成功触发时调用(如按键按下、摇杆推动、鼠标点击,是绝大多数操作的核心事件);
    3. canceled:输入取消触发时调用(如松开按键、摇杆归位);
  • 作用 :为 "跳跃" 动作绑定事件驱动 逻辑 ------ 只有当玩家触发跳跃输入(如按空格)时,才会执行OnJumpPerformed方法,无需在 Update 中逐帧检测,性能更优;
  • 编写要点 :事件绑定写在OnEnable中,保证脚本启用时输入监听生效;绑定格式为「动作名。事件名 += 回调方法名」。
步骤 5:OnDisable 中解绑输入事件(避坑关键)
cs 复制代码
private void OnDisable()
{
    // 必须补充!取消注册Jump事件,避免内存泄漏/空引用报错
    jumpAction.performed -= OnJumpPerformed;
}
  • 核心作用 :当脚本禁用 / 对象销毁时,必须解绑已绑定的输入事件
  • 不解绑的后果 :场景切换、对象销毁时,事件仍会尝试调用脚本中的方法,导致空引用异常内存泄漏
  • 编写要点 :解绑格式与绑定完全一致,仅将+=改为-=,写在OnDisable中,保证与OnEnable的绑定 / 解绑成对出现。
步骤 6:Update 中逐帧读取输入值(状态型输入)

新输入系统中,持续输入的操作(如移动、视角) 适合用「逐帧读取输入值」的方式,脚本中MoveLook均采用此方式,对应 Update 中的两个方法:

子步骤 6.1:HandleMovement 中读取「移动」输入值

cs 复制代码
private void HandleMovement()
{
    // 核心:通过moveAction.ReadValue<Vector2>()逐帧读取移动输入的二维值
    // 对应Input Actions中配置的Move动作(Type=Value,Control Type=Vector2)
    // 返回值:x轴=-1~1(左/右,A/D/方向键左/右),y轴=-1~1(后/前,S/W/方向键下/上)
    moveInput = moveAction.ReadValue<Vector2>();

    // 后续将输入值转为世界空间移动方向(与输入系统无关,是移动逻辑)
    moveDirection = transform.right * moveInput.x + transform.forward * moveInput.y;
    characterController.Move(moveDirection * moveSpeed * Time.deltaTime);
}
  • 核心方法InputAction.ReadValue<T>()------ 新输入系统中读取输入值的统一方法<T>为输入值的类型,需与 Input Actions 中配置的动作类型一致:✅ Move 动作在 Input Actions 中配置为「Type=Value,Control Type=Vector2」,因此用ReadValue<Vector2>();✅ 若为按键动作(如 Fire),可使用ReadValue<bool>()
  • 编写要点 :持续输入的操作(移动、视角、相机拖动),在 Update 中逐帧调用ReadValue<T>()获取最新输入值,保证操作的流畅性。

**子步骤 6.2:**HandleRotation 中读取「视角」输入值

cs 复制代码
private void HandleRotation()
{
    // 核心:读取Look动作的二维输入值(鼠标移动增量/右摇杆值)
    // Look动作在Input Actions中配置为「Type=Value,Control Type=Vector2」,绑定<Mouse>/delta(鼠标移动增量)
    mouseInput = lookAction.ReadValue<Vector2>();

    // 后续将输入值转为旋转逻辑(与输入系统无关,是视角控制逻辑)
    transform.Rotate(Vector3.up * mouseInput.x * mouseSensitivity);
    verticalRotation -= mouseInput.y * mouseSensitivity;
    verticalRotation = Mathf.Clamp(verticalRotation, -90f, 90f);
    playerCamera.transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);
}
  • 输入值说明 :Look 动作通常绑定<Mouse>/delta(鼠标移动增量),因此mouseInput.x鼠标水平移动像素mouseInput.y鼠标垂直移动像素 ,需配合mouseSensitivity(鼠标灵敏度)缩放,避免视角旋转过快;
  • 编写要点 :鼠标视角控制的 Look 动作,必须绑定<Mouse>/delta而非<Mouse>/position(鼠标位置),否则视角会瞬间跳转到鼠标位置,而非平滑跟随鼠标移动。
步骤 7:事件回调方法中处理输入(Jump 动作)
cs 复制代码
// Jump动作的performed事件回调方法,参数必须为InputAction.CallbackContext
private void OnJumpPerformed(InputAction.CallbackContext context)
{
    // 仅当在地面时,执行跳跃逻辑(与输入系统无关,是游戏规则)
    if (isGrounded)
    {
        verticalVelocity = jumpForce;
    }
}
  • 回调方法要求 :绑定InputAction事件的回调方法,必须包含一个InputAction.CallbackContext类型的参数(即使方法中不使用该参数),否则会报 "方法签名不匹配" 错误;
  • 参数作用InputAction.CallbackContext context包含当前输入动作的所有信息 (如输入值、输入设备、输入阶段),例如:
    • 若想在回调中读取输入值,可写context.ReadValue<Vector2>()(与moveAction.ReadValue<Vector2>()效果一致);
  • 编写要点:事件回调方法中只处理「输入触发后的核心逻辑」,游戏规则判断(如是否在地面、是否冷却)写在回调中,保证逻辑内聚。

六、完整操作步骤(总结版)

以上脚本的新输入系统代码,并非纯手写,而是 「编辑器可视化配置」+「脚本代码调用」的结合,完整编写步骤如下:

前置准备:安装新输入系统

  1. 打开 Unity → Window → Package Manager → 搜索Input System → 安装 → 重启 Unity;
  2. 确保玩家对象已添加核心组件。

步骤 1:创建并配置 Input Actions 资源

  1. Project 窗口右键 → Create → Input Actions → 命名为PlayerInputActions
  2. 双击打开该资源,进入可视化配置面板:
    • 创建 Action Map :点击+Add Action Map → 命名为GamePlay(管理游戏核心操作);
    • 配置 Move 动作
      • 点击+Add Action → 命名为Move
      • 类型设为Value,控制类型设为Vector2
      • 点击Move → + → Add Binding → 绑定<Keyboard>/w/a/s/d<Keyboard>/arrowUp/arrowLeft/arrowDown/arrowRight(WASD 和方向键);
    • 配置 Look 动作
      • 点击+Add Action → 命名为Look
      • 类型设为Value,控制类型设为Vector2
      • 点击Look → + → Add Binding → 绑定<Mouse>/delta(鼠标移动增量),若需支持手柄,再绑定<Gamepad>/rightStick(右摇杆);
    • 配置 Jump 动作
      • 点击+Add Action → 命名为Jump
      • 类型设为Button(按键动作,只有触发 / 未触发两种状态);
      • 点击Jump → + → Add Binding → 绑定<Keyboard>/space(空格键);
    • 保存配置 :点击面板右上角Save,关闭面板。

步骤 2:给玩家对象挂载并配置 PlayerInput 组件

  1. 选中玩家对象 → Inspector 面板 → Add Component → 搜索Player Input → 添加组件;
  2. 配置 PlayerInput 组件的核心属性:
    • Actions :将步骤 1 创建的PlayerInputActions资源拖入该字段(关联输入配置);
    • Action Map :选择GamePlay(启用该动作映射);
    • Behavior :选择Send MessagesInvoke Unity Events(脚本中通过playerInput.actions获取动作,此选项不影响,选默认即可);
    • 其他属性保持默认。

步骤 3:编写脚本并挂载

创建 C# 脚本People,按以下顺序编写代码:

  1. 引入命名空间using UnityEngine.InputSystem;
  2. 声明新输入系统相关变量(PlayerInputInputActionVector2输入值);
  3. Awake 中获取PlayerInput组件,并通过playerInput.actions获取 Move/Look/Jump 动作引用;
  4. OnEnable 中绑定 Jump 动作的performed事件到回调方法;
  5. OnDisable 中解绑 Jump 事件;
  6. Update 中调用 HandleMovement 和 HandleRotation,逐帧读取输入值;
  7. 编写输入值的处理逻辑(移动、视角、跳跃回调);

步骤 4:测试与调试

  1. 运行游戏,按 WASD 测试移动、移动鼠标测试视角、按空格测试跳跃;
  2. 若输入无响应,排查以下点:✅ PlayerInput 组件是否关联了 Input Actions 资源;✅ 脚本中获取动作的名称是否与 Input Actions 中完全一致(大小写);✅ OnEnable 中是否绑定了事件,OnDisable 中是否解绑;✅ 鼠标是否锁定(脚本中Cursor.lockState = CursorLockMode.Locked,避免鼠标移出游戏窗口)。

七、核心总结(新输入系统关键要点)

  1. 核心桥梁PlayerInput组件是脚本与可视化配置的 Input Actions 之间的核心桥梁,所有输入动作都通过它获取;
  2. 两种输入方式
    • 持续输入(移动、视角):用InputAction.ReadValue<T>()在 Update 中逐帧读取
    • 单次触发输入(跳跃、射击):用InputAction.事件名 += 回调方法事件驱动,性能更优;
  3. 关键方法 / 类
    • 读取输入值:InputAction.ReadValue<T>()(T 与动作控制类型一致);
    • 事件绑定:InputAction.performed/started/canceled += 回调方法
    • 事件回调参数:必须包含InputAction.CallbackContext
  4. 避坑重点
    • 命名空间必须引入UnityEngine.InputSystem
    • 事件绑定 / 解绑必须成对出现(OnEnable 绑定,OnDisable 解绑);
    • 获取动作的名称必须与 Input Actions 中完全一致(大小写敏感);
    • 鼠标视角的 Look 动作,必须绑定<Mouse>/delta而非<Mouse>/position

该脚本的新输入系统代码,是 Unity 新输入系统的经典用法,适配绝大多数 3D 角色控制场景(如 FPS / 第三人称),掌握后可轻松迁移到其他游戏中。

相关推荐
WarPigs1 小时前
着色器multi_compile笔记
unity·着色器
jghhh012 小时前
基于C# WinForm实现自动在线升级的方案
开发语言·c#
ECHO飞跃 0122 小时前
Unity2019 本地推理 通义千问0.5-1.5B微调导入
人工智能·深度学习·unity·llama
Unity游戏资源学习屋2 小时前
【Unity UI资源包】GUI Pro - Casual Game 专为休闲手游打造的专业级UI资源包
ui·unity
冰凌糕2 小时前
Unity3D Shader 顶点法线外扩实现描边效果
unity
大尚来也2 小时前
从调度到实时:Linux 下 DolphinScheduler 驱动 Flink 消费 Kafka 的实战指南
c#·linq
cici158742 小时前
基于C#的智能仓储上位机系统实现方案
开发语言·c#
星和月2 小时前
Untiy使用说明
c#·游戏引擎
小菱形_3 小时前
【Unity】TimeLine
unity·游戏引擎