# InputDeviceIconSetSO 配置指南 **配置文件**:`Assets/_Game/Data/UI/InputIcons/ICN_*.asset` **对应脚本**:`InputDeviceIconSetSO.cs` · `InputIconService.cs` · `InputDeviceDetector.cs` **创建工具**:Unity 菜单 `BaseGames/Input Icon Studio`(推荐)或 Inspector 右键 `Create > BaseGames/UI/Input Device Icon Set` **影响系统**:`InputIconService` · `InteractPromptWidget` · `InputIconImage` · `InputDeviceIconSwitcher` --- ## 目录 1. [系统架构概述](#1-系统架构概述) 2. [InputDeviceIconSetSO 字段详解](#2-inputdeviceiconsetsoso-字段详解) 3. [IconEntry 绑定路径参考表](#3-iconentry-绑定路径参考表) 4. [图片规格要求](#4-图片规格要求) 5. [InputIconService 配置字段](#5-inputiconservice-配置字段) 6. [设备自动识别逻辑](#6-设备自动识别逻辑) 7. [InteractPromptWidget 配置](#7-interactpromptwidget-配置) 8. [InputIconImage 配置](#8-inputiconimage-配置) 9. [完整工作流:从零到运行](#9-完整工作流从零到运行) 10. [常见问题与排查](#10-常见问题与排查) --- ## 1. 系统架构概述 ``` InputSystem (底层事件) │ ▼ InputDeviceDetector ← 监听所有输入流,精确识别设备类型 │ 广播 InputDeviceTypeEventChannelSO ▼ InputIconService ← 根据设备切换活跃图标集 + 监听改键事件 │ implements IInputIconService ├── _kbMouseSet (ICN_KeyboardMouse.asset) ├── _xboxSet (ICN_Xbox.asset) ├── _playStationSet (ICN_PlayStation.asset) └── _switchSet (ICN_Switch.asset) │ │ GetActionIcon(actionName) │ → GetActionEffectivePath() ← 读取 InputActionAsset + 改键覆盖路径 │ → InputDeviceIconSetSO.GetIcon(path) ▼ UI 消费者: ├── InteractPromptWidget → Image (按键图标) + TMP_Text (动作名称) └── InputIconImage → Image (任意场景内按键提示) ``` ### 核心设计要点 | 要点 | 说明 | |------|------| | **改键自动更新** | `InputIconService.GetActionEffectivePath()` 使用 `binding.effectivePath`,该值已内置玩家改键后的覆盖路径,UI 无需额外处理 | | **多设备无缝切换** | 玩家随时插拔手柄,`InputDeviceDetector` 实时检测最后一次输入来自哪个设备,图标自动切换,无卡顿 | | **回退机制** | 若某设备图标集未配置(null),`InputIconService` 自动回退到键鼠集 | | **不走 Addressables** | 4 套图标集 SO 通过 `SerializeField` 直接挂载在 Persistent 场景的 `InputIconService` 组件上,随常驻场景加载,零加载延迟 | --- ## 2. InputDeviceIconSetSO 字段详解 > 路径:`Assets/_Game/Data/UI/InputIcons/ICN_{设备}.asset` > 菜单:`Create > BaseGames/UI/Input Device Icon Set` ### 2.1 顶层字段 #### `_deviceType`(InputDeviceType 枚举) | 枚举值 | 对应设备 | 说明 | |--------|---------|------| | `KeyboardMouse` | 键盘 + 鼠标 | 默认设备,未识别到手柄时回退到此 | | `XboxController` | Xbox 手柄 / 其他 XInput 手柄 | 包含 Xbox One、Xbox Series、大多数第三方 PC 手柄 | | `PlayStationController` | DualShock 4 / DualSense(PS5)| 通过 Sony 布局层次或 manufacturer 字段识别 | | `SwitchController` | Switch Pro Controller / Joy-Con | 通过 Nintendo 厂商字段或布局识别 | **用途**: - 编辑器工具(Input Icon Studio)用此字段将 SO 自动归类到对应设备标签栏 - `AddressableRules` 工具可依此字段批量校验命名一致性 - **不影响运行时逻辑**:运行时由 `InputIconService` 按字段顺序(_kbMouseSet / _xboxSet / _playStationSet / _switchSet)直接选择,不读取此字段 > ⚠️ 务必与文件命名对应:`ICN_KeyboardMouse.asset` → `KeyboardMouse` --- #### `_entries`(IconEntry 数组) 每个元素代表「一个按键路径 → 一张 Sprite」的映射关系。 | 字段 | 类型 | 说明 | |------|------|------| | `BindingPath` | string | InputSystem 绑定路径(见 §3 参考表)。**大小写不敏感**,匹配时使用 `OrdinalIgnoreCase` | | `Icon` | Sprite | 该按键对应的图标 Sprite(规格要求见 §4)| **注意事项**: 1. **路径必须是 InputSystem 的标准路径格式**,不是自定义字符串。路径来源: - 运行时从 `binding.effectivePath` 获取(含改键) - 编辑时从 `InputActionAsset` 的 Binding 列表获取 - 可在 Input Icon Studio 的 Action 列表中查看当前绑定路径预览 2. **改键后路径会变化**:例如玩家将「跳跃」从 `/space` 改为 `/leftShift`,系统会查询 `/leftShift`。因此图标集中需要覆盖所有玩家可能绑定的物理按键,而非仅默认按键。 3. **同一按键路径在多个 Action 中可复用**:图标集是路径 → Sprite 的扁平映射,一张 Sprite 可对应多个 Action 的查询结果(只要路径相同)。 4. **路径不存在时行为**:`GetIcon()` 返回 `null`,UI 消费方(`InteractPromptWidget` / `InputIconImage`)会将 `Image.enabled = false`,隐藏图标区域,不显示错误占位图。 --- ### 2.2 Inspector 快捷操作(InputDeviceIconSetSOEditor) 在 Inspector 选中 `ICN_*.asset` 时,自定义编辑器提供以下操作: | 按钮 | 功能 | |------|------| | **从 Action Asset 填充路径** | 读取 `InputReaderSO` 中的 `InputActionAsset`,自动提取当前设备方案的所有绑定路径,批量创建 `_entries` 条目(Icon 留空,待手动填入)| | **在 Input Icon Studio 打开** | 跳转到 Input Icon Studio 窗口并定位此 SO | | **复制路径** | 右键单个条目的路径字段,复制路径字符串到剪贴板 | --- ## 3. IconEntry 绑定路径参考表 ### 3.1 键盘常用路径(`ICN_KeyboardMouse.asset`) | 描述 | BindingPath | |------|-------------| | 空格键 | `/space` | | E 键(交互默认) | `/e` | | F 键 | `/f` | | R 键 | `/r` | | Shift 键(左) | `/leftShift` | | Ctrl 键(左) | `/leftCtrl` | | Tab 键 | `/tab` | | Escape 键 | `/escape` | | Enter 键 | `/enter` | | 方向键上 | `/upArrow` | | 方向键下 | `/downArrow` | | 方向键左 | `/leftArrow` | | 方向键右 | `/rightArrow` | | W / A / S / D | `/w` · `/a` · `/s` · `/d` | | 数字键 1~4 | `/1` ~ `/4` | | 鼠标左键 | `/leftButton` | | 鼠标右键 | `/rightButton` | | 鼠标中键 | `/middleButton` | | 滚轮向上 | `/scroll/up` | | 滚轮向下 | `/scroll/down` | ### 3.2 Xbox / XInput 手柄路径(`ICN_Xbox.asset`) | 描述 | BindingPath | |------|-------------| | A 键(南方键,交互默认) | `/buttonSouth` | | B 键(东方键) | `/buttonEast` | | X 键(西方键) | `/buttonWest` | | Y 键(北方键) | `/buttonNorth` | | 左摇杆按下 | `/leftStickButton` | | 右摇杆按下 | `/rightStickButton` | | 左肩键 LB | `/leftShoulder` | | 右肩键 RB | `/rightShoulder` | | 左扳机 LT | `/leftTrigger` | | 右扳机 RT | `/rightTrigger` | | 十字键上 | `/dpad/up` | | 十字键下 | `/dpad/down` | | 十字键左 | `/dpad/left` | | 十字键右 | `/dpad/right` | | 开始键 Start / Menu | `/start` | | 选择键 Select / View | `/select` | | 左摇杆方向 | `/leftStick` | | 右摇杆方向 | `/rightStick` | ### 3.3 PlayStation 手柄路径(`ICN_PlayStation.asset`) > **路径与 Xbox 完全相同**(均使用通用 `` 路径),只有图标 Sprite 不同。 > PlayStation 的按键物理布局与 Xbox 一致(南/东/西/北方键),区别在于图标(✕ / ○ / □ / △ vs A/B/X/Y)。 | 描述 | PS 图标 | BindingPath(与 Xbox 相同) | |------|---------|--------------------------| | 南方键 Cross(✕) | ✕ 图标 | `/buttonSouth` | | 东方键 Circle(○) | ○ 图标 | `/buttonEast` | | 西方键 Square(□) | □ 图标 | `/buttonWest` | | 北方键 Triangle(△) | △ 图标 | `/buttonNorth` | | L1 | L1 图标 | `/leftShoulder` | | R1 | R1 图标 | `/rightShoulder` | | L2 | L2 图标 | `/leftTrigger` | | R2 | R2 图标 | `/rightTrigger` | | L3(左摇杆按下)| L3 图标 | `/leftStickButton` | | R3(右摇杆按下)| R3 图标 | `/rightStickButton` | | Options 键 | Options 图标 | `/start` | | TouchPad / Share | TouchPad 图标 | `/select` | ### 3.4 Nintendo Switch 手柄路径(`ICN_Switch.asset`) > **路径同样与 Xbox/PS 共用 `` 路径**,仅图标不同。 > Switch 的南方键是 B,东方键是 A,与 Xbox 方向相反,务必使用正确的 Switch 图标。 | 描述 | Switch 图标 | BindingPath | |------|------------|-------------| | 南方键 B | B 图标 | `/buttonSouth` | | 东方键 A | A 图标 | `/buttonEast` | | 西方键 Y | Y 图标 | `/buttonWest` | | 北方键 X | X 图标 | `/buttonNorth` | | L 键 | L 图标 | `/leftShoulder` | | R 键 | R 图标 | `/rightShoulder` | | ZL 键 | ZL 图标 | `/leftTrigger` | | ZR 键 | ZR 图标 | `/rightTrigger` | | + 键 | + 图标 | `/start` | | - 键 | - 图标 | `/select` | --- ## 4. 图片规格要求 ### 4.1 分辨率与尺寸 | 场景 | 建议尺寸 | 说明 | |------|---------|------| | **HUD 交互提示**(InteractPromptWidget 主图标)| **64×64 px** | 运行时显示在 32×32 的 Image 控件中,2× 超采样保证清晰度 | | **InputIconImage**(通用场景内提示)| **64×64 px** | 与上同 | | Input Icon Studio 大图预览 | 64×64 px | 编辑器预览用,与运行时同图 | > 最小可用尺寸 **32×32 px**,但在 Retina / 高 DPI 屏幕上会模糊。 > 不建议超过 **128×128 px**(Atlas 占用增大但视觉收益有限)。 ### 4.2 格式 | 项目 | 规范 | |------|------| | **文件格式** | PNG(推荐,支持透明度)| | **色彩模式** | RGBA(需要透明背景)| | **背景** | **透明**,图标主体不超过 90% 画布区域,四周留 5% 安全边距 | | **颜色风格** | 与游戏 UI 风格一致:像素风选用扁平配色;高清风可使用渐变 | ### 4.3 Unity Import Settings 在 Inspector 选中图标 PNG 后,设置以下 Import Settings: | 设置项 | 推荐值 | 原因 | |-------|-------|------| | **Texture Type** | `Sprite (2D and UI)` | 用于 UI Image 组件 | | **Sprite Mode** | `Single`(单图)或 `Multiple`(Sprite Sheet) | 单张图标用 Single;若多个图标合并到一张 Atlas 用 Multiple | | **Pixels Per Unit** | `32`(像素风项目)或 `64`(高清项目,与 Canvas 缩放匹配) | 与项目全局 PPU 保持一致 | | **Filter Mode** | `Point (no filter)`(像素风)或 `Bilinear`(高清风) | 像素风必须用 Point,否则会模糊 | | **Compression** | `None`(开发阶段)/ `ASTC 4x4`(移动端发布)| 图标资产小,压缩感知不明显,开发期优先无损 | | **Generate Mip Maps** | **关闭** | 2D UI 不需要 Mip Maps | | **Read/Write Enabled** | **关闭**(除非代码读像素)| 减少内存占用 | | **Max Size** | `128` | 图标不需要超过 128px | | **Alpha Is Transparency** | **开启** | 正确处理透明边缘抗锯齿 | ### 4.4 Sprite Atlas 策略 将同一设备的所有按键图标合并到一张 Atlas,可减少 DrawCall: | Atlas 文件 | 覆盖内容 | 存放位置 | |-----------|---------|---------| | `Atlas_UI_Keys_KBM.spriteatlas` | 键鼠全部按键图标 | `_Game/Art/UI/Icons/InputKeys/` | | `Atlas_UI_Keys_Xbox.spriteatlas` | Xbox 全部按键图标 | `_Game/Art/UI/Icons/InputKeys/` | | `Atlas_UI_Keys_PS.spriteatlas` | PlayStation 全部按键图标 | `_Game/Art/UI/Icons/InputKeys/` | | `Atlas_UI_Keys_Switch.spriteatlas` | Switch 全部按键图标 | `_Game/Art/UI/Icons/InputKeys/` | > **Atlas 本身不注册 Addressable**,由引用它的 SO 间接带入包体。 ### 4.5 命名规范 ``` IC_Key_{DeviceShort}_{KeyName}.png DeviceShort: KBM → 键盘鼠标 Xbox → Xbox / XInput PS → PlayStation (DualShock/DualSense) Switch → Nintendo Switch 示例: IC_Key_KBM_Space.png ← /space IC_Key_KBM_E.png ← /e IC_Key_KBM_LMB.png ← /leftButton IC_Key_Xbox_South.png ← /buttonSouth (A键) IC_Key_Xbox_RT.png ← /rightTrigger IC_Key_PS_Cross.png ← /buttonSouth (✕键) IC_Key_PS_R2.png ← /rightTrigger IC_Key_Switch_South.png ← /buttonSouth (B键) IC_Key_Switch_ZR.png ← /rightTrigger ``` --- ## 5. InputIconService 配置字段 > 组件挂载位置:`Persistent 场景` → `UIRoot` → `InputIconService` | 字段(Header) | 字段名 | 类型 | 说明 | |--------------|--------|------|------| | **Input** | `_inputReader` | InputReaderSO | 游戏全局 InputReaderSO,用于查询 Action 的绑定路径(含改键覆盖)| | **Icon Sets** | `_kbMouseSet` | InputDeviceIconSetSO | 键鼠图标集(`ICN_KeyboardMouse.asset`)。**默认激活集,任何未识别设备均回退到此** | | **Icon Sets** | `_xboxSet` | InputDeviceIconSetSO | Xbox 图标集(`ICN_Xbox.asset`)。可为 null,null 时回退到 `_kbMouseSet` | | **Icon Sets** | `_playStationSet` | InputDeviceIconSetSO | PlayStation 图标集(`ICN_PlayStation.asset`)。可为 null,null 时回退到 `_kbMouseSet` | | **Icon Sets** | `_switchSet` | InputDeviceIconSetSO | Switch 图标集(`ICN_Switch.asset`)。可为 null,null 时回退到 `_kbMouseSet` | | **Event Channels** | `_onDeviceChanged` | InputDeviceTypeEventChannelSO | 订阅 InputDeviceDetector 广播的设备切换事件(`EVT_InputDeviceChanged.asset`)| ### 5.1 回退规则 ``` 设备切换到 XboxController _xboxSet != null → 使用 _xboxSet _xboxSet == null → 回退 _kbMouseSet 设备切换到 PlayStationController _playStationSet != null → 使用 _playStationSet _playStationSet == null → 回退 _kbMouseSet 设备切换到 SwitchController _switchSet != null → 使用 _switchSet _switchSet == null → 回退 _kbMouseSet ``` > 回退到 `_kbMouseSet` 时,手柄路径(如 `/buttonSouth`)查询 `_kbMouseSet` 会返回 null(因为键鼠集里没有 Gamepad 路径),最终 `Image.enabled = false`,图标区域隐藏。 > **建议**:四套图标集均配置完整,避免出现图标消失的情况。 --- ## 6. 设备自动识别逻辑 > 组件:`InputDeviceDetector`,挂在 `UIRoot` 上,与 `InputIconService` 同节点 ### 6.1 识别优先级 ``` 有输入事件到来时(StateEvent / DeltaStateEvent): 1. device is Keyboard or Mouse → KeyboardMouse 2. device is Gamepad 2a. 布局继承自 DualShockGamepad 或 product 含 "DualShock"/"DualSense" 或 manufacturer 含 "Sony" → PlayStationController 2b. 布局继承自 SwitchProControllerHID 或 product 含 "Switch"/"Joy-Con" 或 manufacturer 含 "Nintendo" → SwitchController 2c. 布局继承自 XInputController 或 product 含 "Xbox" 或 interfaceName == "XInput" → XboxController 2d. 未匹配(第三方 HID 手柄) → XboxController(默认) 3. 其他设备类型(触摸屏等) → KeyboardMouse(默认) ``` ### 6.2 热插拔行为 - 手柄**拔出**:`InputDeviceChange.Removed` 不触发设备切换,保持当前图标集,防止玩家无意拔线导致图标乱跳 - 手柄**重连**:`InputDeviceChange.Reconnected/Added` 同样不自动切换,等待下一次实际输入事件再切换 - 玩家**实际操作**键鼠或手柄时,才触发切换 —— 这是最符合用户体验的设计 --- ## 7. InteractPromptWidget 配置 > 组件挂载位置:`Persistent 场景` → `HUD Canvas` → `InteractPromptWidget_GO` ### 7.1 字段说明 | Header | 字段 | 类型 | 说明 | |--------|------|------|------| | **UI 引用** | `_keyIcon` | Image | 显示按键图标的 UI Image 组件。宽高建议 **32×32**(Canvas 坐标空间),Preserve Aspect = true | | **UI 引用** | `_labelText` | TMP_Text | 显示动作说明文字(如"交互"、"拾取"),对应 `InteractPromptEvent.LabelText` | | **UI 引用** | `_root` | GameObject | 整个提示 UI 的根节点(含图标+文字),`SetActive(false)` 时完整隐藏。若为 null,则控制 Widget 所在 GameObject 本身 | | **Event Channels** | `_onShowPrompt` | InteractPromptEventChannelSO | 订阅此频道接收显示指令,负载为 `InteractPromptEvent { ActionName, LabelText }` | | **Event Channels** | `_onHidePrompt` | VoidEventChannelSO | 订阅此频道接收隐藏指令(玩家离开交互范围时触发)| ### 7.2 InteractPromptEvent 负载 | 字段 | 类型 | 说明 | |------|------|------| | `ActionName` | string | InputSystem Action 名称,如 `"Interact"`。用于在 InputIconService 查询对应图标 | | `LabelText` | string | 显示的文字,如 `"交互"` / `"拾取"` / `"打开"`。由交互物件在广播时指定(来自 `Interactable.InteractPrompt`)| ### 7.3 延迟绑定机制 `InteractPromptWidget` 在 `OnEnable` 时**不**立即获取 `IInputIconService`,而是在首次 `ShowPrompt()` 时才获取。这避免了执行顺序问题(`InputIconService.Awake()` 可能晚于 Widget 的 `OnEnable`)。 --- ## 8. InputIconImage 配置 > 适用场景:教程界面、暂停菜单、任何需要显示单个按键图标的 UI Image > 组件:`InputIconImage`,挂在带有 `Image` 组件的 UI GameObject 上 ### 8.1 字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `_mode` | LookupMode 枚举 | 查询模式(见下表)| | `_actionName` | string | **ByActionName 模式**:填写 Action 名称(如 `"Jump"`),自动跟随改键和设备切换 | | `_bindingPath` | string | **ByBindingPath 模式**:填写固定路径(如 `/space`),不跟随改键 | ### 8.2 LookupMode 枚举 | 枚举值 | 适用场景 | 改键响应 | 设备切换响应 | |--------|---------|---------|------------| | `ByActionName`(推荐)| 所有正常游戏内 UI 提示 | ✅ 自动更新 | ✅ 自动切换 | | `ByBindingPath` | 教程截图说明、固定按键展示(如「按 Space 确认」这类静态文案)| ❌ 不更新 | ❌ 不切换 | > `ByBindingPath` 模式目前图标查询功能为低优先级,实际返回 null(`Image.enabled = false`)。如需支持,可在 `InputIconService` 中通过 `GetOrDefault()` + `GetActiveSet().GetIcon(path)` 手动实现。 --- ## 9. 完整工作流:从零到运行 ### Step 1 · 导入图标素材 ``` 1. 在 _Game/Art/UI/Icons/InputKeys/ 下创建4个子文件夹:KBM / Xbox / PS / Switch 2. 将各设备按键图标 PNG 放入对应子文件夹 3. 在 Unity 中选中所有图标,统一设置 Import Settings: - Texture Type: Sprite (2D and UI) - Sprite Mode: Single - Pixels Per Unit: 32(像素风) - Filter Mode: Point (no filter) - Max Size: 128 - Generate Mip Maps: 关闭 - Alpha Is Transparency: 开启 4. 创建4个 Sprite Atlas(见 §4.4),将图标拖入对应 Atlas ``` ### Step 2 · 创建图标集 SO 方式 A(推荐)— 使用 Input Icon Studio: ``` 1. 菜单 BaseGames/Input Icon Studio 2. 在「图标集资产状态」区域,点击对应设备的「+ 新建」 3. 保存路径:_Game/Data/UI/InputIcons/ICN_{设备}.asset 4. 确认 _deviceType 字段与文件名一致 ``` 方式 B — 手动创建: ``` 1. Project 窗口右键 → Create → BaseGames/UI/Input Device Icon Set 2. 重命名为 ICN_{设备}.asset,移至 _Game/Data/UI/InputIcons/ 3. 在 Inspector 中设置 _deviceType ``` ### Step 3 · 填充绑定路径与图标 ``` 在 Input Icon Studio 中: 1. 顶部选择 InputReaderSO(自动加载唯一实例) 2. 点击设备标签(键鼠 / Xbox / PS / Switch) 3. 左列选择 Action(如 Interact) 4. 右列拖入对应 Sprite 5. 覆盖率圆点变绿(●)= 已配置 或在 Inspector 中直接编辑 _entries 数组: 1. 展开 _entries 2. 点击「从 Action Asset 填充路径」批量生成所有条目(Icon 留空) 3. 逐条拖入 Sprite ``` ### Step 4 · 绑定到 InputIconService ``` 1. 打开 Persistent 场景 2. 选中 UIRoot GameObject(或单独的 InputIconService GameObject) 3. 找到 InputIconService 组件 4. 拖入对应字段: _inputReader → InputReaderSO(通常为 PLY_InputReader.asset) _kbMouseSet → ICN_KeyboardMouse.asset _xboxSet → ICN_Xbox.asset _playStationSet → ICN_PlayStation.asset _switchSet → ICN_Switch.asset _onDeviceChanged → EVT_InputDeviceChanged.asset ``` ### Step 5 · 配置 InteractPromptWidget ``` 1. 在 HUD Canvas 下找到(或创建)InteractPromptWidget GameObject 2. 挂上 InteractPromptWidget 组件 3. 配置字段: _keyIcon → 按键图标 Image 组件(32×32 UI Image) _labelText → 动作说明 TMP_Text 组件 _root → 整个提示 UI 根节点(控制显隐) _onShowPrompt → EVT_ShowInteractPrompt.asset _onHidePrompt → EVT_HideInteractPrompt.asset ``` ### Step 6 · 验证 ``` 进入 PlayMode: ✅ 走近 NPC / 宝箱 → 右下角显示按键图标 + "交互"文字 ✅ 插入 Xbox 手柄 → 图标自动切换为 Xbox A 键图标 ✅ 插入 DualShock → 图标切换为 PS ✕ 图标 ✅ 改键(在游戏内按键重映射菜单)→ 图标同步更新 ✅ 拔出手柄 → 恢复键鼠图标(下次键盘/鼠标操作后切换) ``` --- ## 10. 常见问题与排查 ### 图标不显示(Image 被隐藏) 1. 检查 `InputIconService` 的4个图标集字段是否已赋值 2. 检查 `_entries` 中是否有该 Action 对应设备的绑定路径条目 3. 在 Input Icon Studio 左列查看该 Action 的绑定路径预览,与 `_entries` 中的 BindingPath 对比 4. 检查 `InputReaderSO` 是否正确赋值给 `InputIconService._inputReader` 5. 运行时打开 Event Bus Monitor(`BaseGames/Events/Event Bus Monitor`)确认 `EVT_InputDeviceChanged` 是否正常广播 ### 改键后图标不更新 1. 确认 `InputIconService.OnEnable()` 已订阅 `InputSystem.onActionChange`(Inspector 中确保组件处于 active 状态) 2. 确认 `_entries` 中包含改键后目标按键的路径(如玩家改到 `/leftShift`,需有对应条目) 3. 改键后图标集必须覆盖所有可能被绑定的物理按键;对于玩家自定义改键的游戏,建议将整个键盘的常用键全部配置进 `_kbMouseSet._entries` ### 设备切换后图标不更新 1. 确认 `InputDeviceDetector` 组件已挂载在场景中(UIRoot 上) 2. 确认 `InputDeviceDetector._onDeviceChanged` 与 `InputIconService._onDeviceChanged` 引用的是**同一个** `EVT_InputDeviceChanged.asset` 3. 插入手柄后需要实际按下任意按键才会触发识别(纯插入不切换) ### PlayStation 手柄显示 Xbox 图标 1. 在 Unity 菜单 `Window > Analysis > Input Debugger` 查看手柄的 `layout` 字段 2. 若 layout 不继承自 `DualShockGamepad`(部分 USB 适配器会出现此情况),系统会回退到 XboxController 3. 可在 `InputDeviceDetector.ClassifyDevice()` 中添加额外的 product 字符串匹配规则 ### 编辑器工具显示覆盖率为 0/0 - 说明 `InputReaderSO` 未在 Input Icon Studio 工具栏加载,或 `InputActionAsset` 的 Gameplay ActionMap 为空 - 在工具栏 ObjectField 手动指定 InputReaderSO,然后点击「⟳ 刷新」 --- ## 附录:相关文件速查 | 用途 | 文件路径 | |------|---------| | 图标集 SO(键鼠)| `_Game/Data/UI/InputIcons/ICN_KeyboardMouse.asset` | | 图标集 SO(Xbox)| `_Game/Data/UI/InputIcons/ICN_Xbox.asset` | | 图标集 SO(PS)| `_Game/Data/UI/InputIcons/ICN_PlayStation.asset` | | 图标集 SO(Switch)| `_Game/Data/UI/InputIcons/ICN_Switch.asset` | | 按键图标图片 | `_Game/Art/UI/Icons/InputKeys/` | | 核心 SO 脚本 | `Scripts/UI/InputDeviceIconSetSO.cs` | | 服务接口 | `Scripts/UI/IInputIconService.cs` | | 服务实现 | `Scripts/UI/InputIconService.cs` | | 设备检测器 | `Scripts/UI/InputDeviceDetector.cs` | | 交互提示 Widget | `Scripts/UI/HUD/InteractPromptWidget.cs` | | 通用图标 Image | `Scripts/UI/InputDeviceIconSwitcher.cs`(含 InputIconImage 类)| | 编辑器窗口 | `Scripts/Editor/Input/InputIconStudioWindow.cs` | | 编辑器 Inspector | `Scripts/Editor/Input/InputDeviceIconSetSOEditor.cs` | | 事件频道 | `Data/Events/UI/EVT_InputDeviceChanged.asset` | | 交互提示事件 | `Data/Events/World/EVT_ShowInteractPrompt.asset` |