总览
一个真正能用的改键界面,不是“捕获玩家按下的键然后保存”。它还要回答四个问题:这个键是否被保留?会不会遮住现有映射?会不会被现有映射遮住?键的类型和 Action 值类型是否匹配?
Query API
Subsystem 提供两个查询:
TArray<FMappingQueryIssue> Issues;
const EMappingQueryResult Result = Subsystem->QueryMapKeyInActiveContextSet(
DefaultMappingContext,
JumpAction,
EKeys::SpaceBar,
Issues,
DefaultMappingIssues::StandardFatal);
QueryMapKeyInActiveContextSet 用当前玩家已激活的 Context 集合;QueryMapKeyInContextSet 可以传一个自定义的优先级 Context 列表,适合设置页预览某个方案。
Issue 含义
| Issue | 大白话 | UI 建议 |
|---|---|---|
| ReservedByAction | 被另一个 Action 独占保留 | 直接拒绝 |
| HidesExistingMapping | 新映射会遮住已有映射 | 提示覆盖 |
| HiddenByExistingMapping | 新映射会被已有映射挡住 | 提示无效 |
| CollisionWithMappingInSameContext | 同 Context 内冲突 | 让玩家确认或拒绝 |
| ForcesTypePromotion | 低维键绑定高维 Action | 警告 |
| ForcesTypeDemotion | 高维轴绑定低维 Action | 通常拒绝 |
DefaultMappingIssues::StandardFatal 包括保留、冲突和类型不匹配。你可以按项目需求放宽,例如允许同一个键同时打开地图和关闭地图,但不要默认全部放行。
保留键
UInputAction 有 bReserveAllMappings。当一个 Action 保留所有映射时,Query 会返回 ReservedByAction,表示别的 Action 不应该抢这个键。适合系统级输入:Esc、截图、调试开关、无障碍快捷键。
改键 UI 流程
玩家点击“更改键位”
-> UI 进入等待输入状态
-> 捕获第一个有效 FKey
-> QueryMapKeyInActiveContextSet
-> 无 fatal issue:MapPlayerKey + ApplySettings + SaveSettings
-> 可覆盖 issue:弹窗确认,确认后先 UnMap/覆盖,再保存
-> fatal issue:显示原因,继续等待或取消
UI 文案要说人话:“空格已经绑定到跳跃,是否改为翻滚并清除跳跃的空格键?”不要直接显示 HidesExistingMapping。
类型匹配案例
把键盘 W 绑给 IA_Move Axis2D 可以接受,因为映射级 Modifier 会把 1D 拼成 2D;把 Mouse X 这种 1D 轴绑给 Boolean Action 就很怪;把 Gamepad Left Stick 2D 绑给 Axis1D Action 可能丢掉 Y 轴。Query 的类型升降级 issue 就是提醒你别让玩家做出不可理解的绑定。
UI 数据结构建议
设置页不要直接存一堆按钮文本。建议每一行保存:
MappingNameDisplayNameDisplayCategorySlotCurrentKeyDefaultKeyHardwareDeviceIdAssociatedInputAction
这些都能从 FPlayerKeyMapping 读到。UI 只负责展示和发起改键,不要自己维护另一套真相。
常见坑
- 改键前不 Query,玩家能把移动、交互、开火全绑到 E。
- Query 只看当前 IMC,设置页却允许改未激活的载具/菜单 Context。
- 覆盖时只设置新键,没有清理被覆盖动作的旧键,导致两个动作共用。
- 对保留键只弹警告但仍允许保存,后续调试很痛苦。
- 捕获键位时把鼠标移动 delta 当成要绑定的键。
源码依据
InputMappingQuery.h 定义 EMappingQueryResult、EMappingQueryIssue、FMappingQueryIssue 和 DefaultMappingIssues::StandardFatal。IEnhancedInputSubsystemInterface 暴露 QueryMapKeyInActiveContextSet、QueryMapKeyInContextSet、QueryKeysMappedToAction 和 GetAllPlayerMappableActionKeyMappings。
源码路径索引
EnhancedInput/Public/InputMappingQuery.hEnhancedInput/Public/EnhancedInputSubsystemInterface.hEnhancedInput/Public/InputAction.hEnhancedInput/Public/UserSettings/EnhancedInputUserSettings.h