Unity3D 进阶教程 - 18 新版 Input System 深入

概述

入门系列使用 Input.GetAxis / Input.GetButtonDown(旧版 Input Manager)。新版 Input System 是 Unity 推荐的输入处理方案,从 Unity 2019 开始引入,Unity 2023 以后旧版已标记为过时。

新 Input System 的核心优势:多设备统一处理可重绑定按键事件驱动输入调试工具

1. 启用 Input System

1
Package Manager -> Unity Registry -> Input System -> Install

安装后建议在 Project Settings > Player > Active Input Handling 中选择 Both。


2. 核心概念

概念 说明
Input Action Asset 输入映射配置文件
Action Map 一组相关 Action,如 Gameplay、UI、Menu
Action 一个具体的操作,如 Move、Jump、Fire
Binding Action 到具体输入设备的映射

3. 代码集成

3.1 自动生成 C# 类

在 Input Action Asset 的 Inspector 中勾选 Generate C# Class,生成后的代码提供强类型 API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class PlayerInputController : MonoBehaviour
{
private InputActions _input;
private Vector2 _moveInput;

private void Awake()
{
_input = new InputActions();
}

private void OnEnable()
{
_input.Gameplay.Enable();
}

private void OnDisable()
{
_input.Gameplay.Disable();
}

private void Update()
{
_moveInput = _input.Gameplay.Move.ReadValue<Vector2>();
}

private void OnDestroy()
{
_input?.Dispose();
}
}

3.2 事件驱动模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class EventDrivenPlayer : MonoBehaviour
{
private InputActions _input;

private void OnEnable()
{
_input = new InputActions();
_input.Gameplay.Enable();

_input.Gameplay.Jump.performed += OnJump;
_input.Gameplay.Fire.performed += OnFire;
}

private void OnDisable()
{
_input.Gameplay.Jump.performed -= OnJump;
_input.Gameplay.Fire.performed -= OnFire;
_input.Gameplay.Disable();
}

private void OnJump(InputAction.CallbackContext context)
{
if (IsGrounded())
_rb.AddForce(Vector3.up * _jumpForce, ForceMode.Impulse);
}

private void OnFire(InputAction.CallbackContext context)
{
if (context.performed)
Shoot();
}
}

4. 按键重绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class RebindingUI : MonoBehaviour
{
[SerializeField] private InputActionReference _jumpAction;

public void StartRebinding()
{
var action = _jumpAction.action;
var bindingIndex = action.GetBindingIndexForControl(action.controls[0]);

action.Disable();

action.PerformInteractiveRebinding(bindingIndex)
.WithControlsExcluding("Mouse")
.WithTimeout(5f)
.OnComplete(result =>
{
Debug.Log("重绑定完成: " + result.selectedControl.path);
action.Enable();

var json = action.SaveBindingOverridesAsJson();
PlayerPrefs.SetString("Rebindings", json);
})
.OnCancel(result =>
{
Debug.Log("重绑定取消");
action.Enable();
})
.Start();
}

public void LoadSavedBindings()
{
if (PlayerPrefs.HasKey("Rebindings"))
{
var json = PlayerPrefs.GetString("Rebindings");
_jumpAction.action.LoadBindingOverridesFromJson(json);
}
}
}

5. 多设备支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class DeviceManager : MonoBehaviour
{
[SerializeField] private GameObject _playerPrefab;

private void Start()
{
InputSystem.onDeviceChange += OnDeviceChange;

foreach (var device in InputSystem.devices)
{
if (device is Gamepad || device is Keyboard)
AssignPlayerToDevice(device);
}
}

private void OnDeviceChange(InputDevice device, InputDeviceChange change)
{
switch (change)
{
case InputDeviceChange.Added:
AssignPlayerToDevice(device);
break;
case InputDeviceChange.Removed:
UnassignPlayerFromDevice(device);
break;
}
}

private void AssignPlayerToDevice(InputDevice device)
{
var player = Instantiate(_playerPrefab);
var input = player.GetComponent<PlayerInput>();
input.SwitchCurrentControlScheme(device);
}
}

6. 输入调试

1
Window -> Analysis -> Input Debugger

功能:查看所有已连接的设备、实时输入值、检查绑定是否生效。


总结

  • Input Action Asset 是输入配置的中央仓库
  • 三种读取方式:直接轮询(ReadValue)、事件驱动(performed)、自动生成 C# 类
  • 按键重绑定 是 Input System 的原生功能
  • Input Debugger 是排查输入问题的首选工具

下一篇将讲解 高级物理与自定义碰撞,超越 Unity 内置物理引擎的限制。

ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: