1. Unity新输入系统全面解析
Unity的新输入系统(Input System)是Unity Technologies官方推出的现代化输入解决方案,旨在取代传统的Input Manager。作为一名使用Unity开发过多款跨平台游戏的开发者,我深刻体会到这套新系统带来的变革性优势。
重要提示:新输入系统需要Unity 2019.4或更高版本,并通过Package Manager安装。建议使用Unity 2021 LTS或更新版本以获得最完整的功能支持。
1.1 为什么需要新输入系统?
传统Input Manager存在几个致命缺陷:
- 硬编码严重:输入键位直接写在代码中,难以适应不同设备
- 扩展性差:添加新输入设备需要修改大量代码
- 跨平台支持弱:不同平台需要单独处理输入逻辑
新输入系统的核心优势在于:
- 设备无关性:通过抽象层将具体输入设备与游戏逻辑解耦
- 可视化配置:所有输入映射可通过编辑器界面配置,无需硬编码
- 多设备支持:自动处理键盘、鼠标、手柄、触屏等多种输入设备
- 动态重绑定:运行时允许玩家自定义按键设置
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 安装Input System Package
- 打开Unity编辑器,选择Window > Package Manager
- 在Packages列表中找到"Input System"并安装
- 安装完成后会提示重启编辑器
csharp复制// 安装后需在代码中添加命名空间引用
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
2.2 切换输入处理模式
重启编辑器后需要进行关键配置:
- 菜单栏选择Edit > Project Settings > Player
- 找到"Active Input Handling"选项
- 根据项目情况选择:
- Input System Package (New):全新项目推荐
- Both:需要兼容旧系统的项目
经验分享:如果选择"Both",可以通过
UnityEngine.InputSystem.EnhancedTouch.Touch.onFingerDown和Input.GetMouseButton(0)同时监听新旧系统的触摸/点击事件,但要注意避免逻辑冲突。
3. 两种核心使用模式详解
3.1 直接设备查询模式
适合快速原型开发或简单游戏场景,代码结构与旧Input Manager类似:
csharp复制public class DirectInputExample : MonoBehaviour
{
public float moveSpeed = 5f;
void Update()
{
// 键盘输入检测
var keyboard = Keyboard.current;
if (keyboard != null)
{
Vector2 moveInput = Vector2.zero;
if (keyboard.wKey.isPressed) moveInput.y += 1;
if (keyboard.sKey.isPressed) moveInput.y -= 1;
if (keyboard.aKey.isPressed) moveInput.x -= 1;
if (keyboard.dKey.isPressed) moveInput.x += 1;
transform.Translate(moveInput * moveSpeed * Time.deltaTime);
}
// 鼠标输入检测
var mouse = Mouse.current;
if (mouse != null && mouse.leftButton.wasPressedThisFrame)
{
Debug.Log($"点击位置:{mouse.position.ReadValue()}");
}
// 手柄输入检测
var gamepad = Gamepad.current;
if (gamepad != null)
{
Vector2 stickInput = gamepad.leftStick.ReadValue();
transform.Translate(new Vector3(stickInput.x, 0, stickInput.y) *
moveSpeed * Time.deltaTime);
if (gamepad.buttonSouth.wasPressedThisFrame)
{
Debug.Log("手柄A键按下");
}
}
}
}
优缺点分析:
- 优点:编码简单直观,适合快速测试
- 缺点:设备依赖性强,难以支持按键重绑定
3.2 基于Input Actions的推荐模式
这是新输入系统的核心用法,通过创建Input Actions资源文件来定义所有输入逻辑。
3.2.1 创建Input Actions资源
- 在Project窗口右键 > Create > Input Actions
- 命名为"PlayerControls"(建议命名规范)
- 双击打开Input Actions编辑器
3.2.2 配置Action Maps和Actions
- Action Maps:逻辑输入分组
- 例如:"Gameplay"、"UI"、"Vehicle"等
- Actions:抽象输入动作
- 类型:Value(连续值)、Button(按钮)、PassThrough(直通)
典型配置示例:
- 创建"Gameplay" Action Map
- 添加以下Actions:
- Move (Value/Vector2):角色移动
- Look (Value/Vector2):视角控制
- Jump (Button):跳跃
- Fire (Button):开火
- Sprint (Button):冲刺
3.2.3 绑定物理输入
为每个Action添加Bindings:
- 对于Move动作:
- 添加"2D Vector Composite"
- 分别绑定WASD键和手柄左摇杆
- 对于Jump动作:
- 绑定空格键和手柄A键
- 对于Fire动作:
- 绑定鼠标左键和手柄RT键
专业技巧:可以为同一个Action添加多个Bindings,系统会自动选择当前活动的输入设备。
3.2.4 生成C#脚本
- 选中Input Actions资源
- 在Inspector中勾选"Generate C# Class"
- 点击Apply生成包装类
生成的类提供了强类型访问接口,例如:
csharp复制var controls = new PlayerControls();
controls.Gameplay.Move.performed += OnMove;
4. 代码实现与架构设计
4.1 基础实现模式
csharp复制public class PlayerController : MonoBehaviour
{
private PlayerControls controls;
private Vector2 moveInput;
private Vector2 lookInput;
private bool isJumping;
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float lookSensitivity = 1f;
void Awake()
{
controls = new PlayerControls();
}
void OnEnable()
{
// 注册输入回调
controls.Gameplay.Move.performed += ctx => moveInput = ctx.ReadValue<Vector2>();
controls.Gameplay.Move.canceled += _ => moveInput = Vector2.zero;
controls.Gameplay.Look.performed += ctx => lookInput = ctx.ReadValue<Vector2>();
controls.Gameplay.Look.canceled += _ => lookInput = Vector2.zero;
controls.Gameplay.Jump.performed += _ => isJumping = true;
controls.Gameplay.Jump.canceled += _ => isJumping = false;
controls.Enable();
}
void OnDisable()
{
controls.Disable();
}
void Update()
{
// 处理移动
Vector3 movement = new Vector3(moveInput.x, 0, moveInput.y) *
moveSpeed * Time.deltaTime;
transform.Translate(movement);
// 处理视角旋转
Vector3 rotation = new Vector3(-lookInput.y, lookInput.x, 0) *
lookSensitivity;
transform.Rotate(rotation);
// 处理跳跃
if (isJumping)
{
// 跳跃逻辑...
}
}
}
4.2 进阶架构设计
对于复杂项目,推荐采用分层架构:
- 输入层:只负责收集原始输入
csharp复制public class InputProvider : MonoBehaviour
{
public event Action<Vector2> OnMove;
public event Action<Vector2> OnLook;
public event Action OnJump;
private PlayerControls controls;
void Awake() => controls = new PlayerControls();
void OnEnable()
{
controls.Gameplay.Move.performed += ctx => OnMove?.Invoke(ctx.ReadValue<Vector2>());
controls.Gameplay.Look.performed += ctx => OnLook?.Invoke(ctx.ReadValue<Vector2>());
controls.Gameplay.Jump.performed += _ => OnJump?.Invoke();
controls.Enable();
}
void OnDisable() => controls.Disable();
}
- 逻辑层:处理游戏逻辑
csharp复制public class PlayerMovement : MonoBehaviour
{
[SerializeField] private InputProvider inputProvider;
[SerializeField] private float moveSpeed = 5f;
void OnEnable()
