Skip to content

新版输入系统

unity-new-input-system-learning-map

一句话理解

新版 Input System 不再让代码直接问:

玩家是不是按了 W?
玩家是不是按了空格?

而是改成问:

玩家是否触发了 Move?
玩家是否触发了 Jump?
玩家是否触发了 Fire?

也就是:

c
旧版:按键驱动
新版:动作驱动

核心结构

你要记住这条链:

c
Device -> Control -> Binding -> Action -> Action Map -> PlayerInput -> 代码

意思是:

c
Device:设备,比如 Keyboard、Mouse、Gamepad
Control:设备上的控件,比如 space、leftStick、leftButton
Binding:绑定,比如 <Keyboard>/space
Action:动作,比如 Jump、Move、Fire
Action Map:动作组,比如 Gameplay、UI、Vehicle
PlayerInput:把输入动作发给玩家脚本

官方当前 latest 文档指向 Input System 1.20.0。Unity 文档也明确说,Actions 的意义是把“输入目的”和“具体设备控件”分离。

最推荐的新手用法:PlayerInput + Input Actions

  1. 创建输入资产:
c
Assets > Create > Input Actions

命名:

c
PlayerControls.inputactions

打开它,创建 Action Map

c
Gameplay

Gameplay 里创建 Actions:

c
Move   Value / Vector2
Jump   Button
Fire   Button
Look   Value / Vector2
Pause  Button

Move 加绑定:

c
2D Vector Composite
Up: W
Down: S
Left: A
Right: D

再加:

c
<Gamepad>/leftStick
  1. Jump 加绑定:
c
<Keyboard>/space
<Gamepad>/buttonSouth
  1. 玩家物体上添加组件:
c
PlayerInput

设置:

c
Actions: PlayerControls
Default Map: Gameplay
Behavior: Invoke Unity Events

移动案例

c
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f;

    private Vector2 moveInput;

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

    public void OnJump(InputAction.CallbackContext context)
    {
        if (!context.performed) return;

        Debug.Log("Jump");
    }

    private void Update()
    {
        Vector3 move = new Vector3(moveInput.x, 0f, moveInput.y);
        transform.Translate(move * moveSpeed * Time.deltaTime, Space.World);
    }
}

然后在 PlayerInput 的 Unity Events 里绑定:

c
Gameplay / Move -> PlayerController.OnMove
Gameplay / Jump -> PlayerController.OnJump

重点:Move 是持续值,不要只在 performed 里移动一次。正确做法是保存 moveInput,再在 Update 里持续移动。

started、performed、canceled

新版输入动作有阶段:

c
started:开始触发
performed:触发成功
canceled:结束或取消

跳跃通常只看:

c
if (context.performed)
{
    Jump();
}

蓄力攻击可能这样用:

c
started:开始蓄力
performed:蓄力完成并释放
canceled:松开太早,取消蓄力

Interactions 和 Processors

Interactions 决定“怎么按才算触发”:

c
Press:普通按下
Hold:长按
Tap:短按
MultiTap:多次点击

Processors 决定“输入值怎么处理”:

c
Deadzone:摇杆死区
Normalize:归一化
Invert:反转
Scale:缩放
Clamp:限制

比如视角上下反了,可以给 Look 的 Y 轴加反转处理。

Action Map 的意义

不要所有输入都塞在一组里。推荐:

c
Gameplay:Move、Jump、Fire、Look
UI:Navigate、Submit、Cancel
Vehicle:Steer、Brake、Boost

暂停时切换:

c
using UnityEngine;
using UnityEngine.InputSystem;

public class InputModeSwitcher : MonoBehaviour
{
    [SerializeField] private PlayerInput playerInput;

    public void OpenMenu()
    {
        playerInput.SwitchCurrentActionMap("UI");
    }

    public void CloseMenu()
    {
        playerInput.SwitchCurrentActionMap("Gameplay");
    }
}

直接读设备,适合小测试

c
using UnityEngine;
using UnityEngine.InputSystem;

public class DirectInputTest : MonoBehaviour
{
    private void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            Debug.Log("Space");
        }

        if (Mouse.current.leftButton.wasPressedThisFrame)
        {
            Debug.Log("Left click");
        }

        Vector2 mousePosition = Mouse.current.position.ReadValue();
    }
}

这种方式简单,但不适合正式项目,因为键位写死,后面不好支持手柄、改键、多平台。

最常见错误

c
忘记 using UnityEngine.InputSystem
Action 没有 Enable,手写 InputAction 时尤其常见
Move 设置成 Button,却用 ReadValue<Vector2>()
PlayerInput 没拖 .inputactions
Default Map 没选 Gameplay
UI 还在用 Standalone Input Module
移动逻辑只写在 performed 里,导致角色只动一下
旧版 Input.GetAxis 和新版 InputSystem 混用导致报错

你现在的学习顺序

c
1. 会创建 .inputactions
2. 会建 Gameplay / Move / Jump / Fire
3. 会用 PlayerInput 调用脚本
4. 会区分 Button 和 Value
5. 会 ReadValue<Vector2>()
6. 会切换 Action Map
7. 再学 Interactions、Processors、Control Schemes、改键

记住这句就稳了:

c
Action 写游戏意图,Binding 写设备按法,PlayerInput 把动作送到代码。

参考:Unity 官方 Input System 1.20.0ActionsInput Action AssetsBindingsPlayerInputPlayerInput Behavior

文章评价

读完这篇,留下你的看法

暂无审核通过的评价。

登录账号后才能评价。

本站访客数0总站访问量0本页访问量0