总览
UI 输入最常见的 bug 是:打开背包后角色还在走;Esc 同时关闭菜单又触发暂停;手柄打开菜单后焦点不在按钮上;长按交互在暂停时还继续触发。解决思路不是在每个回调里堆 if (bMenuOpen),而是把 UI 作为输入层管理。
基本做法
打开 UI 时:
- 添加
IMC_Menu,优先级高于 gameplay。 - 设置 PlayerController 的输入模式,例如 GameAndUI 或 UIOnly。
- 设置焦点到第一个可选 Widget。
- 如果启用 Input Mode Filtering,给 Enhanced Input 设置
Input.Mode.MenuTag。 - 关闭 UI 时反向恢复。
Subsystem->AddMappingContext(MenuMappingContext, 100);
Subsystem->AddTagToInputMode(TAG_InputMode_Menu);
Pause 下是否触发
UInputAction 有 bTriggerWhenPaused。暂停菜单里的 Cancel、Confirm、Navigate 通常需要在暂停时触发;角色移动、攻击、交互不应该。不要全局让所有输入暂停时可触发。
UI Context 设计
| UI | Context | 动作 |
|---|---|---|
| 暂停菜单 | IMC_Menu |
Confirm、Cancel、Navigate、Tab |
| 背包 | IMC_Inventory |
Navigate、Equip、Drop、Compare |
| 对话 | IMC_Dialog |
Continue、Skip、ChoiceUpDown |
| 径向菜单 | IMC_Radial |
StickDirection、Confirm、Cancel |
这些 Context 可以共享部分 Input Action,比如 IA_UIConfirm、IA_UICancel,也可以按 UI 独立拆分。
Gameplay 与 UI 的返回键
Esc 或手柄 B 是最容易冲突的键。建议把“打开暂停”和“UI 返回”拆成两个 Action:
IA_OpenPause在 Gameplay Context。IA_UICancel在 UI Context。
打开 UI 后移除或过滤 Gameplay Context,让 Esc 只走 UI Cancel。关闭最后一层 UI 后恢复 Gameplay。
Consume 与焦点
高优先级 IMC_Menu 可以遮住低优先级 gameplay 映射;UI Widget 自身也可能处理键盘/手柄事件。项目要明确“输入先到 Enhanced Input 还是先到 Slate/UI”。如果用 CommonUI,通常让 UI Action Router 管 UI 导航,Enhanced Input 负责 gameplay 和需要统一改键的 UI Action。
使用案例:背包里仍可旋转角色
有些游戏打开背包时允许右摇杆旋转角色预览,但禁止移动。做法不是保留完整 Default Context,而是拆出 IMC_LookOnly 或给背包加专用 PreviewRotate Action。这样不会让 Move、Jump、Interact 漏进来。
使用案例:径向菜单
按住 LB 打开径向菜单,左摇杆选择方向,松开确认。可以用:
IA_RadialOpen:Hold 或 Down。IA_RadialDirection:Axis2D。IMC_Radial:打开时加高优先级。
关闭时移除 IMC_Radial,不要让角色 Move 同时消费左摇杆。
常见坑
- UI 打开后只
SetInputModeUIOnly,但 Enhanced Input Context 没改,某些 Action 仍触发。 bTriggerWhenPaused给了 Gameplay Action,暂停时还能攻击。- 手柄 UI 没设置焦点,Confirm Action 有触发但 Widget 不响应。
- Esc 同时存在 Gameplay 和 UI Context,关闭菜单后立刻又打开。
- UI 改键和 Gameplay 改键用两套系统,玩家设置不一致。
源码依据
UInputAction 提供 bTriggerWhenPaused、消费相关字段和 TriggerEventsThatConsumeLegacyKeys。IEnhancedInputSubsystemInterface 提供 InputMode 的 Get/Set/Add/Remove Tag API。UInputMappingContext 支持 InputModeQuery,项目设置里 bEnableInputModeFiltering 控制是否按当前 InputMode 过滤映射。
源码路径索引
EnhancedInput/Public/EnhancedInputSubsystemInterface.hEnhancedInput/Public/InputAction.hEnhancedInput/Public/InputMappingContext.hEnhancedInput/Public/EnhancedInputDeveloperSettings.h