2026-03-26 16:45:24 +08:00
|
|
|
|
# Input
|
|
|
|
|
|
|
|
|
|
|
|
**命名空间**: `XCEngine::Input`
|
|
|
|
|
|
|
|
|
|
|
|
**类型**: `module`
|
|
|
|
|
|
|
2026-03-26 17:39:53 +08:00
|
|
|
|
**描述**: 提供输入状态查询、逻辑轴与按钮映射、同步事件分发以及平台输入桥接接口。
|
2026-03-26 16:45:24 +08:00
|
|
|
|
|
2026-03-26 17:39:53 +08:00
|
|
|
|
## 概述
|
2026-03-26 16:45:24 +08:00
|
|
|
|
|
2026-03-26 17:39:53 +08:00
|
|
|
|
`XCEngine::Input` 解决的是“如何把平台消息变成引擎可查询输入状态”这个问题。当前模块的核心由两层组成:
|
|
|
|
|
|
|
2026-04-08 16:07:03 +08:00
|
|
|
|
- `InputManager` 负责保存键盘、鼠标的按住态、本帧按下边沿、本帧释放边沿、鼠标位移和滚轮状态,并同步广播输入事件。
|
2026-03-26 17:39:53 +08:00
|
|
|
|
- `InputModule` 负责定义平台桥接接口,把操作系统窗口消息翻译成 `InputManager::Process*` 调用。
|
|
|
|
|
|
|
|
|
|
|
|
当前版本的成熟度是分层的:
|
|
|
|
|
|
|
|
|
|
|
|
- 键盘与鼠标的基础轮询和事件分发已经可用,并且有单元测试覆盖。
|
2026-04-08 16:07:03 +08:00
|
|
|
|
- Windows 路径已经有实际桥接实现 [WindowsInputModule](../Platform/Windows/WindowsInputModule/WindowsInputModule.md)。
|
2026-03-26 17:39:53 +08:00
|
|
|
|
- 触摸与摇杆相关 API 仍然偏预留位,当前 `InputManager` 自身并不会产生这些输入。
|
|
|
|
|
|
|
2026-04-08 16:07:03 +08:00
|
|
|
|
## 当前帧语义
|
|
|
|
|
|
|
|
|
|
|
|
当前输入模块明确区分三类状态:
|
|
|
|
|
|
|
|
|
|
|
|
- 按住态
|
|
|
|
|
|
- `IsKeyDown()`、`IsMouseButtonDown()`、`GetAxis()`、`GetAxisRaw()`、`GetButton()`、`IsAnyKeyDown()`
|
|
|
|
|
|
- 抬起态
|
|
|
|
|
|
- `IsKeyUp()`、`IsMouseButtonUp()`
|
|
|
|
|
|
- 这类查询只是“当前没有按住”,不是“本帧刚释放”
|
|
|
|
|
|
- 边沿态
|
|
|
|
|
|
- 按下边沿: `IsKeyPressed()`、`IsMouseButtonClicked()`、`GetButtonDown()`、`IsAnyKeyPressed()`
|
|
|
|
|
|
- 释放边沿: `IsKeyReleased()`、`IsMouseButtonReleased()`、`GetButtonUp()`
|
|
|
|
|
|
|
|
|
|
|
|
这里最容易误解的点有两个:
|
|
|
|
|
|
|
|
|
|
|
|
- `IsKeyUp()` / `IsMouseButtonUp()` 与 `IsKeyReleased()` / `IsMouseButtonReleased()` 不是一回事。
|
|
|
|
|
|
- `GetAxisRaw()` 当前和 `GetAxis()` 使用同一套实现,都会根据持续按住状态返回 `-1 / 0 / 1`;它现在不是“只在本帧按下才非零”的边沿接口。
|
|
|
|
|
|
- 键盘按下边沿查询当前不会过滤 `repeat`。如果平台在后续帧继续发送重复 `KeyDown`,`IsKeyPressed()`、`GetButtonDown()`、`IsAnyKeyPressed()` 仍可能再次成立。
|
|
|
|
|
|
|
2026-03-26 17:39:53 +08:00
|
|
|
|
## 设计要点
|
|
|
|
|
|
|
|
|
|
|
|
- 同时保留轮询接口和事件接口,方便游戏逻辑与 UI 系统按各自习惯接入。
|
|
|
|
|
|
- 逻辑轴和逻辑按钮采用名字映射,风格上接近 Unity 旧版 Input Manager,而不是设备级输入系统。
|
|
|
|
|
|
- 平台桥接与输入状态解耦,`InputModule` 可以替换,而游戏代码继续依赖 `InputManager`。
|
|
|
|
|
|
- 当前实现是轻量级同步模型,不是线程安全的跨平台输入框架。
|
|
|
|
|
|
|
|
|
|
|
|
## 当前实现限制
|
|
|
|
|
|
|
2026-04-08 16:07:03 +08:00
|
|
|
|
- `GetAxisRaw()` 当前与 `GetAxis()` 完全一致,都不做平滑、重力或灵敏度处理。
|
|
|
|
|
|
- 默认注册的 `Mouse X` / `Mouse Y` 轴虽然存在,但仍绑定到 `KeyCode::None`,所以当前查询结果始终为 `0.0f`。
|
|
|
|
|
|
- 键盘按下边沿语义是“本帧收到 `ProcessKeyDown()` 消息”,不是“严格意义上的首次物理按下”。
|
|
|
|
|
|
- `ClearAxes()` 会同时清空轴和按钮映射,名字比实际行为更窄。
|
2026-03-26 17:39:53 +08:00
|
|
|
|
- `InputTypes::KeyCode` 的底层数值当前存在重复项,而 `InputManager` 又直接把这些值当作数组下标。
|
2026-04-08 16:07:03 +08:00
|
|
|
|
- `InputManager::Shutdown()` 不会清空事件监听器;如果跨生命周期复用单例,需要调用方自己管理订阅。
|
2026-03-26 17:39:53 +08:00
|
|
|
|
- `InputManager` 暴露了触摸接口,但当前代码路径没有填充触摸状态。
|
2026-03-26 16:45:24 +08:00
|
|
|
|
|
|
|
|
|
|
## 头文件
|
|
|
|
|
|
|
2026-03-26 17:39:53 +08:00
|
|
|
|
- [InputAxis](InputAxis/InputAxis.md) - `InputAxis.h`,逻辑轴配置对象。
|
|
|
|
|
|
- [InputEvent](InputEvent/InputEvent.md) - `InputEvent.h`,输入事件结构体定义。
|
|
|
|
|
|
- [InputManager](InputManager/InputManager.md) - `InputManager.h`,全局输入状态与事件中心。
|
|
|
|
|
|
- [InputModule](InputModule/InputModule.md) - `InputModule.h`,平台输入桥接接口。
|
|
|
|
|
|
- [InputTypes](InputTypes/InputTypes.md) - `InputTypes.h`,键盘、鼠标和摇杆的基础枚举。
|
|
|
|
|
|
|
|
|
|
|
|
## 相关指南
|
|
|
|
|
|
|
2026-04-08 16:07:03 +08:00
|
|
|
|
- [Input Flow And Frame Semantics](../../_guides/Input/Input-Flow-and-Frame-Semantics.md) - 解释事件、轮询、边沿状态、帧边界和平台桥接如何配合工作。
|
2026-03-26 17:39:53 +08:00
|
|
|
|
|
|
|
|
|
|
## 相关实现
|
|
|
|
|
|
|
|
|
|
|
|
- [WindowsInputModule](../Platform/Windows/WindowsInputModule/WindowsInputModule.md) - Windows 平台当前的具体输入桥接实现。
|
2026-03-26 16:45:24 +08:00
|
|
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
|
|
|
|
|
|
- [上级目录](../XCEngine.md)
|
|
|
|
|
|
- [API 总索引](../../main.md)
|