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

3.5 KiB
Raw Blame History

Input Flow And Frame Semantics

这套输入系统怎么理解

当前 XCEngine 输入系统更接近“轻量级、同步、帧驱动的输入管理器”,而不是完整设备抽象框架。

它有两个核心层:

  • InputModule 负责接平台消息。
  • InputManager 负责保存状态并提供事件与查询接口。

这意味着真正的输入流向是:

  1. 平台窗口系统产生命令或消息。
  2. 平台后端把消息翻译成 ProcessKeyDownProcessMouseMove 一类调用。
  3. InputManager 更新状态并同步广播事件。
  4. 游戏或工具层在当前帧读取轮询状态。
  5. Update() 在帧边界清理瞬时状态。

为什么同时保留事件和轮询

事件和轮询各有适合的地方:

  • UI、输入法、编辑器面板更适合订阅事件。
  • 游戏逻辑、相机控制、角色移动更适合每帧轮询。

InputManager 同时提供这两种方式,是为了避免你在上层自己重复维护一套输入缓存。

帧边界怎么理解

当前实现里,Update() 不是“采集输入”,而是“结束上一帧的瞬时状态”。

它会清理:

  • IsKeyPressed 依赖的本帧按下标记
  • IsMouseButtonClicked 依赖的本帧点击标记
  • GetMouseDelta
  • GetMouseScrollDelta

所以最重要的实践是:

  • 每帧只调用一次 Update()
  • 保持调用时机一致。
  • 在清理之前,先消费掉当前帧的瞬时输入。

和 Unity 的对照

从使用方式上看,InputManager 很像 Unity 旧版 Input Manager

  • 有具名轴:HorizontalVertical
  • 有具名按钮:JumpFire1Fire2Fire3
  • 查询接口偏向 GetAxis / GetButton

但当前实现并不等同于 Unity

  • 没有平滑、重力、灵敏度、死区等高级参数。
  • GetAxisRaw 当前只在“按下这一帧”返回非零,不等同于 Unity 中“原始持续值”的语义。
  • Mouse XMouse Y 默认虽然被注册了,但当前实现并不会通过鼠标移动更新它们。

平台桥接是怎么接进来的

InputModule 的意义是把平台消息层隔离掉。当前 Windows 路径里:

  • WindowsInputModule::HandleMessage 负责处理 WM_KEYDOWNWM_MOUSEMOVEWM_MOUSEWHEEL 等消息。
  • 它再调用 InputManager::Process* 统一更新状态。

这样做的好处是:

  • 游戏层不用知道 Win32 消息细节。
  • 将来如果换 GLFW、SDL 或其它平台层,InputManager 可以不变。

当前版本最该知道的限制

  • KeyCode 底层值当前有重复,部分键会共享状态槽。
  • Windows 路径当前不能准确区分左右 Ctrl / Alt / Shift。
  • 触摸与摇杆接口基本是预留位。
  • 事件回调是同步执行的,不是异步消息队列。
  • Shutdown() 当前不会清空事件监听器;如果单例跨生命周期反复初始化,要自己管理订阅者。

推荐使用方式

初始化阶段:

using namespace XCEngine::Input;

InputManager::Get().Initialize(windowHandle);

平台消息阶段:

windowsInputModule.HandleMessage(hwnd, msg, wParam, lParam);

游戏逻辑阶段:

if (InputManager::Get().GetButton("Jump")) {
    // ...
}

帧边界阶段:

InputManager::Get().Update(deltaTime);

相关 API