# InputModule 常见问题 ## 编译错误 ### `CS0117: 'GameEntry' does not contain a definition for 'InputModule'` **原因:** 基座项目的 `GameEntry.Custom.cs` 中没有添加 `InputModule` 静态属性。 **解决:** 1. 在 `GameEntry.Custom.cs` 中添加: ```csharp public static InputModuleComponent InputModule { get; private set; } ``` 2. 在 `InitCustomComponents()` 中赋值: ```csharp InputModule = UnityGameFramework.Runtime.GameEntry.GetComponent(); ``` > 如果项目决定**不接入** InputModule,请确保场景中没有挂载 `VirtualJoystickBridge` / `VirtualButtonBridge`(或删除 `Presentation/` 目录)。这两个 bridge 会自动查找场景中的 `InputModuleComponent`,但不再硬编码依赖 `GameEntry.InputModule`。 ### `The type or namespace name 'InputModuleComponent' could not be found` **原因:** 使用了 `InputModuleComponent` 的代码所在程序集没有引用 `SepCore.Runtime` 或 `SepCore.InputModule.Base`。 **解决:** 检查相关 `.asmdef` 的 `references` 中是否包含 `SepCore.Runtime`(因为 `InputModuleComponent` 通过 `asmref` 编译进 `SepCore.Runtime`)。 ### `SepCore.Presentation` 编译失败,找不到 `InputCommand` 等类型 **原因:** `SepCore.Presentation.asmdef` 没有引用 `SepCore.InputModule.Base`。 **解决:** 在 `SepCore.Presentation.asmdef` 的 `references` 中添加 `GUID:d54b9488b03814a44ab937f0aeb738b1`(即 `SepCore.InputModule.Base`)。 --- ## 运行时问题 ### Play 后输入没有反应 **检查清单:** 1. `Launcher` 场景中是否挂载了 `InputModuleComponent` 2. 启动 Procedure 中是否调用了 `GameEntry.InputModule?.OnInit()` 3. 当前上下文是否正确设置(默认初始化后为 `None`,需要 `SetContext` 或 `SetGameplayExploreContext`) 4. 是否有 listener 注册到了正确的 `InputActionId` ### UI 打开后 Gameplay 输入没有禁用 **原因:** 没有使用 `PushContext(InputContextId.Dialog)` 或 `SetContext(InputContextId.UI)`。 **解决:** - 对于覆盖层弹窗(从 Gameplay 打开 Dialog):使用 `PushContext(InputContextId.Dialog)`,关闭时 `PopContext()` - 对于大场景切换(Menu -> Main):使用 `SetContext(InputContextId.GameplayExplore)` ### 重绑后绑定没有保存 **原因:** `InputModuleComponent` 的 `_saveBindingOverridesOnDestroy` 为 `false`,且没有手动调用 `SaveBindingOverrides()`。 **解决:** - 在 Inspector 中勾选 `_saveBindingOverridesOnDestroy` - 或在重绑成功后手动调用 `GameEntry.InputModule.SaveBindingOverrides()` ### 重绑时报冲突 **原因:** 新绑定的按键与 Global map 或同一 map 内的其他 action 冲突。 **解决:** 当前设计不允许同设备冲突绑定。如果确实需要共享按键(例如同一按钮在不同上下文下做不同的事),应通过上下文切换来隔离,而不是把两个 action 绑定到同一个按键上。 --- ## 设备与提示 ### 手柄插入后 UI 提示没有刷新 **原因:** 没有监听 `DeviceKindChanged` 事件。 **解决:** ```csharp GameEntry.InputModule.DeviceKindChanged += OnDeviceChanged; private void OnDeviceChanged(InputDeviceKind kind) { // 刷新所有按键提示 } ``` ### 触摸虚拟摇杆后设备类型没有变为 Touch **原因:** `VirtualJoystickBridge` 的 `_injectDeviceKind` 为 `false`。 **解决:** 在 Inspector 中勾选 `_injectDeviceKind`。 --- ## 设计约束 ### 能否在业务代码里直接判断 `CurrentDeviceKind == Gamepad`? **不推荐。** 业务层应消费 `InputCommand` 的语义值,设备判断留给 UI/Presentation 层。如果确实需要,建议通过 `DeviceKindChanged` 事件在 UI 层做适配,而不是分散在 gameplay 逻辑中。 ### 为什么 UI 点击不经过 InputModule? 这是 P2 的设计决策:UI 原始输入(点击、拖拽、导航)继续由 Unity EventSystem 处理。InputModule 只负责 gameplay 语义输入和上下文切换。这样避免了双重分发和跨平台复杂度。 ### 能否把 InputModule 完全独立成一个不依赖 UGF 的模块? 当前版本有 3 个地方依赖 UGF: 1. `InputModuleComponent` 继承自 `GameFrameworkComponent` 2. 绑定覆盖持久化使用 `SettingComponent` 3. `GameEntry` 接入约定 如果要完全剥离 UGF,需要: - 把 `InputModuleComponent` 改为普通 `MonoBehaviour` - 自己实现设置持久化接口 - 去掉 `GameEntry` 相关的接入模板 这不是当前 P6 的目标,但架构上 `Base` 层本身已经零依赖 UGF。