Files
XCEngine/docs/api/_guides/Input/Input-Flow-and-Frame-Semantics.md

116 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Input Flow And Frame Semantics
## 这套输入系统怎么理解
当前 XCEngine 输入系统更接近“轻量级、同步、帧驱动的输入管理器”,而不是完整设备抽象框架。
它有两个核心层:
- `InputModule` 负责接平台消息。
- `InputManager` 负责保存状态并提供事件与查询接口。
这意味着真正的输入流向是:
1. 平台窗口系统产生命令或消息。
2. 平台后端把消息翻译成 `ProcessKeyDown``ProcessMouseMove` 一类调用。
3. `InputManager` 更新状态并同步广播事件。
4. 游戏或工具层在当前帧读取轮询状态。
5. `Update()` 在帧边界清理瞬时状态。
## 为什么同时保留事件和轮询
事件和轮询各有适合的地方:
- UI、输入法、编辑器面板更适合订阅事件。
- 游戏逻辑、相机控制、角色移动更适合每帧轮询。
`InputManager` 同时提供这两种方式,是为了避免你在上层自己重复维护一套输入缓存。
## 帧边界怎么理解
当前实现里,`Update()` 不是“采集输入”,而是“结束上一帧的瞬时状态”。
它会清理:
- `IsKeyPressed` 依赖的本帧按下标记
- `IsMouseButtonClicked` 依赖的本帧点击标记
- `GetMouseDelta`
- `GetMouseScrollDelta`
所以最重要的实践是:
- 每帧只调用一次 `Update()`
- 保持调用时机一致。
- 在清理之前,先消费掉当前帧的瞬时输入。
## 和 Unity 的对照
从使用方式上看,`InputManager` 很像 Unity 旧版 Input Manager
- 有具名轴:`Horizontal``Vertical`
- 有具名按钮:`Jump``Fire1``Fire2``Fire3`
- 查询接口偏向 `GetAxis` / `GetButton`
但当前实现并不等同于 Unity
- 没有平滑、重力、灵敏度、死区等高级参数。
- `GetAxisRaw` 当前只在“按下这一帧”返回非零,不等同于 Unity 中“原始持续值”的语义。
- `Mouse X``Mouse Y` 默认虽然被注册了,但当前实现并不会通过鼠标移动更新它们。
## 平台桥接是怎么接进来的
`InputModule` 的意义是把平台消息层隔离掉。当前 Windows 路径里:
- `WindowsInputModule::HandleMessage` 负责处理 `WM_KEYDOWN``WM_MOUSEMOVE``WM_MOUSEWHEEL` 等消息。
- 它再调用 `InputManager::Process*` 统一更新状态。
这样做的好处是:
- 游戏层不用知道 Win32 消息细节。
- 将来如果换 GLFW、SDL 或其它平台层,`InputManager` 可以不变。
## 当前版本最该知道的限制
- `KeyCode` 底层值当前有重复,部分键会共享状态槽。
- Windows 路径当前不能准确区分左右 Ctrl / Alt / Shift。
- 触摸与摇杆接口基本是预留位。
- 事件回调是同步执行的,不是异步消息队列。
- `Shutdown()` 当前不会清空事件监听器;如果单例跨生命周期反复初始化,要自己管理订阅者。
## 推荐使用方式
初始化阶段:
```cpp
using namespace XCEngine::Input;
InputManager::Get().Initialize(windowHandle);
```
平台消息阶段:
```cpp
windowsInputModule.HandleMessage(hwnd, msg, wParam, lParam);
```
游戏逻辑阶段:
```cpp
if (InputManager::Get().GetButton("Jump")) {
// ...
}
```
帧边界阶段:
```cpp
InputManager::Get().Update(deltaTime);
```
## 相关 API
- [Input](../../XCEngine/Input/Input.md)
- [InputManager](../../XCEngine/Input/InputManager/InputManager.md)
- [InputModule](../../XCEngine/Input/InputModule/InputModule.md)
- [InputTypes](../../XCEngine/Input/InputTypes/InputTypes.md)