mcpField
U
unity-input

unity-input

github.com/nice-wolf-studio开发4075 次安装6 周前更新
代码仓库

关于 unity-input

unity-input 是面向 Unity 开发者的 Input System 指南,介绍基于动作的输入配置与读取,以及与旧版输入管理器的区别。内容涵盖多设备输入、本地多人、交互、触控和运行时重绑定。

主要功能

  1. 01InputAction 与 Action Map
  2. 02PlayerInput 本地多人管理
  3. 03轮询与事件回调读取输入
  4. 04键盘、手柄、鼠标和触控
  5. 05输入交互与处理器
  6. 06运行时重绑定和设备发现

适用场景

  1. 01配置跨设备的玩家操作
  2. 02在游戏与 UI 输入映射间切换
  3. 03实现本地多人设备分配
  4. 04添加运行时按键重绑定

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nice-wolf-studio/unity-claude-skills --skill unity-input

安装后在 Claude Code 中输入/unity-input确认已加载。

附带文件references/input-system-api.md

详细介绍

Unity Input System

Input System 概述:新系统与旧系统

Unity 提供两种输入系统:

功能新 Input System(推荐)旧版 Input Manager
包com.unity.inputsystem(Unity 6.3 对应 v1.19.0)内置(UnityEngine.Input)
架构基于操作、事件驱动基于轮询
设备支持游戏手柄、键盘、鼠标、触控、XR、自定义设备键盘、鼠标、摇杆
多人游戏通过 PlayerInput 内置本地多人游戏支持手动实现
重新绑定支持运行时重新绑定不支持
跨平台按设备类型配置 Control Scheme手动编写各平台代码

新的 Input System 是通过 Package Manager 安装的包。它以基于操作的模型取代旧版 Input.GetKey/Input.GetAxis API,将输入用途与设备控件分离。

命名空间: UnityEngine.InputSystem

快速入门设置

1. 安装包

通过 Window > Package Manager > Unity Registry > Input System 安装。

2. 创建默认的项目级操作

前往 Edit > Project Settings > Input System Package > Input Actions,然后点击 "Create and assign a default project-wide Action Asset"。

这会创建默认的 Action Map:

  • Player:移动、视角、跳跃、攻击
  • UI:导航、提交、取消

每个操作都包含键盘、游戏手柄、XR 控制器和触摸屏的绑定。

3. 在脚本中读取输入
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    InputAction moveAction;
    InputAction jumpAction;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
        jumpAction = InputSystem.actions.FindAction("Jump");
    }

    void Update()
    {
        Vector2 moveValue = moveAction.ReadValue<Vector2>();
        transform.Translate(new Vector3(moveValue.x, 0, moveValue.y) * Time.deltaTime * 5f);

        if (jumpAction.IsPressed())
        {
            // Jump logic
        }
    }
}

如果多个地图中存在同名操作,请同时指定两者:"Player/Move"。

Input Actions 和 Action Maps

核心概念
  • InputAction:有名称的操作,可返回控件值或触发回调
  • InputActionMap:相关操作的命名集合(例如 "Player"、"UI"、"Vehicle")
  • InputBinding:操作与设备控件之间的关联
  • InputSystem.actions:对项目级操作的引用
创建操作

方法 1 — Input Actions Editor(推荐): 通过 Project Settings 进行配置 > Input System Package。

方法 2 — MonoBehaviour 字段: 直接在脚本中声明 InputAction 字段(可在 Inspector 中配置)。

方法 3 — 代码:

var moveAction = new InputAction("Move", InputActionType.Value);
moveAction.AddCompositeBinding("Dpad")
    .With("Up", "<Keyboard>/w").With("Down", "<Keyboard>/s")
    .With("Left", "<Keyboard>/a").With("Right", "<Keyboard>/d");
moveAction.Enable();

方法 4 — JSON: var map = InputActionMap.FromJson(jsonString);

操作生命周期

操作初始状态为禁用。必须调用 .Enable() 才能响应输入。启用时无法修改绑定;请先调用 .Disable()。

Input Action 资源(.inputactions)

这些 JSON 文件用于存储操作、绑定和控制方案。通过 Assets > Create > Input Actions 创建。

自动生成的 C# 类: 在资源的导入器中启用 "Generate C# Class",即可获得类型安全的访问方式:

public class MyPlayerScript : MonoBehaviour, IGameplayActions
{
    MyPlayerControls controls;

    public void OnEnable()
    {
        controls = new MyPlayerControls();
        controls.gameplay.SetCallbacks(this);
        controls.gameplay.Enable();
    }

    public void OnDisable()
    {
        controls.gameplay.Disable();
    }

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

PlayerInput 组件

PlayerInput 组件将 Input Actions 映射到脚本方法,并通过设备筛选和屏幕分割处理本地多人游戏。

设置
  1. 将 PlayerInput 组件添加到玩家 GameObject
  2. 将 Action Asset 分配给 Actions 字段
  3. 选择一个 Default Action Map
  4. 选择一种 Behavior 通知类型
Behavior 选项
Behavior机制最适用于
Send MessagesGameObject.SendMessage()简单原型开发
Broadcast Messages沿层级调用 BroadcastMessage()组件层级结构
Invoke Unity Events在 Inspector 中配置事件路由便于设计师连线
Invoke C# EventsonActionTriggered、onDeviceLost、onDeviceRegained由程序员控制
Send Messages 模式
public class PlayerActions : MonoBehaviour
{
    public void OnJump()
    {
        // Called when Jump action triggers (no parameters)
    }

    public void OnMove(InputValue value)
    {
        Vector2 v = value.Get<Vector2>();
        // InputValue is only valid during this callback
    }
}
Unity Events 模式
public void OnFire(InputAction.CallbackContext context)
{
    if (context.performed)
    {
        // Fire logic
    }
}
管理 PlayerInput
PlayerInput playerInput = GetComponent<PlayerInput>();
playerInput.DeactivateInput();                      // Disable all input
playerInput.ActivateInput();                         // Re-enable with default map
playerInput.SwitchCurrentActionMap("Vehicle");       // Switch action map

在代码中读取输入

轮询(在 Update 中)
// 2D movement axis
Vector2 move = moveAction.ReadValue<Vector2>();

// Button state
if (jumpAction.IsPressed()) { /* held down */ }
if (jumpAction.WasPressedThisFrame()) { /* just pressed */ }
if (jumpAction.WasReleasedThisFrame()) { /* just released */ }
回调(事件驱动)
void OnEnable()
{
    fireAction.started += OnFireStarted;
    fireAction.performed += OnFirePerformed;
    fireAction.canceled += OnFireCanceled;
    fireAction.Enable();
}

void OnDisable()
{
    fireAction.started -= OnFireStarted;
    fireAction.performed -= OnFirePerformed;
    fireAction.canceled -= OnFireCanceled;
    fireAction.Disable();
}

void OnFireStarted(InputAction.CallbackContext ctx) { /* Input began */ }
void OnFirePerformed(InputAction.CallbackContext ctx) { /* Completed */ }
void OnFireCanceled(InputAction.CallbackContext ctx) { /* Interrupted */ }

游戏手柄 / 键盘 / 鼠标 / 触控

游戏手柄
using UnityEngine.InputSystem;

// Current gamepad (null if none connected)
var gp = Gamepad.current;
if (gp == null) return;

Vector2 leftStick = gp.leftStick.ReadValue();
bool southPressed = gp.buttonSouth.isPressed;

// Access by enum
gp[GamepadButton.LeftShoulder].isPressed;
gp[GamepadButton.Y].isPressed;          // Xbox style
gp[GamepadButton.Triangle].isPressed;   // PlayStation style

// Rumble / Haptics
gp.SetMotorSpeeds(0.25f, 0.75f); // low-frequency, high-frequency
gp.ResetHaptics();

// Global haptics control
InputSystem.PauseHaptics();
InputSystem.ResumeHaptics();
InputSystem.ResetHaptics();

支持的游戏手柄:DualShock 3/4、DualSense、Xbox(XInput/Bluetooth)、Switch Pro。通用 HID 游戏手柄会显示为通用摇杆,而非 Gamepad 设备。

键盘和鼠标
var kb = Keyboard.current;
if (kb.spaceKey.wasPressedThisFrame) { /* space pressed */ }

var mouse = Mouse.current;
Vector2 mousePos = mouse.position.ReadValue();
float scroll = mouse.scroll.ReadValue().y;
bool leftClick = mouse.leftButton.isPressed;
触控

两个 API 级别:

低级 — 触摸屏设备:

var ts = Touchscreen.current;
if (ts.primaryTouch.press.isPressed)
{
    Vector2 pos = ts.primaryTouch.position.ReadValue();
}

高级 — EnhancedTouch API:

using UnityEngine.InputSystem.EnhancedTouch;

void OnEnable() => EnhancedTouchSupport.Enable();
void OnDisable() => EnhancedTouchSupport.Disable();

void Update()
{
    foreach (var touch in Touch.activeTouches)
    {
        Debug.Log($"{touch.touchId}: {touch.screenPosition}, {touch.phase}");
    }
}

触控阶段:Began、Moved、Stationary、Ended、Cancelled。

使用 Actions 实现多点触控: 绑定 <Touchscreen>/touch*/press,并将 action 类型设为 PassThrough,即可接收每次触控的回调。

触控模拟: 在开发期间,通过 TouchSimulation.Enable() 启用鼠标/触控笔的触控模拟。

设备发现
// Monitor device connections
InputSystem.onDeviceChange += (device, change) =>
{
    if (change == InputDeviceChange.Added)
        Debug.Log($"Device connected: {device.displayName}");
};

交互和处理器

交互定义了驱动 action 阶段的输入模式。

交互阶段
阶段含义
Waiting等待输入
Started已接收输入,但尚未完成
Performed交互完成 — 主要响应触发点
Canceled交互已中断
内置交互
交互说明关键参数
Default自动应用;行为因 action 类型而异—
Press明确的按钮按下行为pressPoint、behavior(PressOnly/ReleaseOnly/PressAndRelease)
Hold持续按下达到最短时长duration、pressPoint
Tap快速按下并释放duration、pressPoint
SlowTap按住后释放duration、pressPoint
MultiTap重复点击序列tapTime、tapDelay、tapCount、pressPoint
通过代码添加交互
var action = new InputAction("fire");
action.AddBinding("<Gamepad>/buttonSouth")
    .WithInteractions("tap(duration=0.8)");
点击与按住示例(开火与蓄力)
var fireAction = new InputAction("fire");
fireAction.AddBinding("<Gamepad>/buttonSouth").WithInteractions("tap,slowTap");
fireAction.started += ctx => { if (ctx.interaction is SlowTapInteraction) ShowChargingUI(); };
fireAction.performed += ctx => {
    if (ctx.interaction is SlowTapInteraction) ChargedFire(); else Fire();
};
fireAction.canceled += _ => HideChargingUI();
fireAction.Enable();
自定义交互

实现 IInputInteraction,然后注册:InputSystem.RegisterInteraction<T>()。完整示例请参阅 references/input-system-api.md。

常见模式

切换 Action Map(例如,游戏玩法与 UI)
public class GameStateManager : MonoBehaviour
{
    PlayerInput playerInput;

    void Start() => playerInput = GetComponent<PlayerInput>();

    public void EnterMenu() => playerInput.SwitchCurrentActionMap("UI");
    public void ExitMenu() => playerInput.SwitchCurrentActionMap("Player");
}
运行时重新绑定
var rebindOp = action.PerformInteractiveRebinding()
    .WithControlsExcluding("Mouse")
    .OnMatchWaitForAnother(0.1f)
    .OnComplete(op =>
    {
        Debug.Log($"Rebound to: {op.action.bindings[0].effectivePath}");
        op.Dispose();
    })
    .Start();
为同一个 Action 添加多个绑定(WASD + 方向键)
var moveAction = new InputAction("Move", InputActionType.Value);
moveAction.AddCompositeBinding("2DVector")
    .With("Up", "<Keyboard>/w").With("Down", "<Keyboard>/s")
    .With("Left", "<Keyboard>/a").With("Right", "<Keyboard>/d");
moveAction.AddCompositeBinding("2DVector")
    .With("Up", "<Keyboard>/upArrow").With("Down", "<Keyboard>/downArrow")
    .With("Left", "<Keyboard>/leftArrow").With("Right", "<Keyboard>/rightArrow");

反模式

反模式问题正确做法
使用 Input.GetKey()(旧版)与新版 Input System 不兼容;不支持重新绑定和多设备使用带绑定的 InputAction
未调用 .Enable() 就读取 ActionsActions 初始处于禁用状态,不会返回任何值始终在 OnEnable() 中调用 action.Enable()
清理时忘记调用 .Disable()导致内存泄漏和幽灵回调在 OnDisable() 中调用 action.Disable()
action 启用时修改绑定会引发异常修改前调用 .Disable(),然后再调用 .Enable()
在游戏玩法代码中硬编码设备路径破坏跨平台支持改用 Actions + Control Schemes
在回调之外使用 InputValue该值仅在回调帧内有效立即将该值复制到字段中
不做空值检查就访问 Gamepad.current未连接游戏手柄时会崩溃始终检查 if (Gamepad.current == null) return;
不取消订阅 action 回调场景重新加载时会导致错误在 OnDisable() 中取消订阅
在生产环境中使用 SendMessages 行为反射会带来性能开销使用 Invoke Unity Events 或 Invoke C# Events
未启用 EnhancedTouch 就对其进行轮询返回空集合首先调用 EnhancedTouchSupport.Enable()

API 快速参考

API用途
InputSystem.actions全项目范围的操作
InputSystem.actions.FindAction("name")按名称查找操作
action.ReadValue<T>()读取当前值
action.IsPressed()检查按钮是否按住
action.WasPressedThisFrame()检查按钮是否刚刚按下
action.WasReleasedThisFrame()检查按钮是否刚刚释放
action.Enable() / action.Disable()启用/停用
action.started / performed / canceled回调事件
action.AddBinding("path")在代码中添加绑定
action.AddCompositeBinding("type")添加复合绑定(Dpad、2DVector)
.WithInteractions("tap(duration=0.5)")为绑定添加交互
Gamepad.current当前游戏手柄引用
Keyboard.current / Mouse.current当前键盘/鼠标
Touchscreen.current当前触摸屏
EnhancedTouchSupport.Enable()启用增强触摸 API
Touch.activeTouches所有活动触摸(增强模式)
InputSystem.onDeviceChange设备连接事件
PlayerInput.SwitchCurrentActionMap()更改当前活动的操作映射
action.PerformInteractiveRebinding()开始运行时重新绑定

相关技能

  • unity-scripting — MonoBehaviour 生命周期、C# 模式
  • unity-ui — UI Toolkit 输入集成、InputSystemUIInputModule
  • unity-xr — XR 控制器输入、追踪设备

其他资源

评论

支持 Markdown