Add InputDeviceIconSetSO configuration guide and related documentation
- Created a new markdown file detailing the configuration of InputDeviceIconSetSO. - Included sections on system architecture, field explanations, image specifications, and complete workflow from setup to runtime. - Documented the automatic device recognition logic and provided troubleshooting for common issues. - Added references to relevant files and scripts for easier navigation.
This commit is contained in:
384
Docs/Tuning/InputDeviceIconSetSO_Tuning.md
Normal file
384
Docs/Tuning/InputDeviceIconSetSO_Tuning.md
Normal file
@@ -0,0 +1,384 @@
|
||||
# InputDeviceIconSetSO 配置指南
|
||||
|
||||
**配置文件**:`Assets/_Game/Data/UI/InputIcons/ICN_*.asset`
|
||||
**对应脚本**:`InputDeviceIconSetSO.cs` · `InputIconService.cs` · `InputDeviceDetector.cs`
|
||||
**创建工具**:Unity 菜单 `BaseGames/Input Icon Studio` 或 Inspector 自定义编辑器
|
||||
**影响系统**:`InputIconService` · `InteractPromptWidget` · `InputDeviceIconSwitcher` · `InputIconImage`
|
||||
|
||||
---
|
||||
|
||||
## 一、系统架构概述
|
||||
|
||||
```
|
||||
InputDeviceDetector (挂在 UIRoot)
|
||||
│ 侦听底层输入事件,识别当前设备类型
|
||||
│ 广播 InputDeviceTypeEventChannelSO
|
||||
▼
|
||||
InputIconService (挂在 UIRoot,IInputIconService 实现)
|
||||
│ 订阅设备切换事件,切换当前图标集
|
||||
│ 订阅 InputSystem.onActionChange,改键后刷新
|
||||
│ SerializeField 直接持有 4 套 InputDeviceIconSetSO 引用
|
||||
│
|
||||
├── _kbMouseSet → ICN_KeyboardMouse.asset
|
||||
├── _xboxSet → ICN_Xbox.asset
|
||||
├── _playStationSet → ICN_PlayStation.asset
|
||||
└── _switchSet → ICN_Switch.asset
|
||||
│
|
||||
▼
|
||||
InputDeviceIconSetSO
|
||||
├── _deviceType (编辑器标识,匹配工具过滤)
|
||||
└── _entries[] (绑定路径 → Sprite 的映射表)
|
||||
│
|
||||
▼
|
||||
GetIcon(bindingPath) → Sprite?
|
||||
|
||||
UI 消费层
|
||||
├── InteractPromptWidget 按键提示 HUD 组件
|
||||
├── InputDeviceIconSwitcher 静态 Sprite 切换(不随改键变化)
|
||||
└── InputIconImage 动态图标(支持 ByActionName 模式,随改键自动刷新)
|
||||
```
|
||||
|
||||
**核心原则**:
|
||||
`InputDeviceIconSetSO` 是**纯数据容器**,本身无运行时逻辑;查询、缓存、刷新均由 `InputIconService` 负责。每套 SO 对应一个输入设备,相互独立,方便美术分别维护。
|
||||
|
||||
---
|
||||
|
||||
## 二、InputDeviceIconSetSO 字段详解
|
||||
|
||||
### 2.1 顶层字段
|
||||
|
||||
| 字段 | 类型 | 序列化名 | 说明 |
|
||||
|------|------|---------|------|
|
||||
| Device Type | `InputDeviceType` 枚举 | `_deviceType` | 标识本图标集对应的设备类型。**不影响运行时选择逻辑**(选择由 `InputIconService` 按字段引用决定),但供编辑器工具(Input Icon Studio)过滤、分组显示。 |
|
||||
| Entries | `IconEntry[]` 数组 | `_entries` | 全部绑定路径与图标的映射表,核心数据。数组顺序不影响查询结果(逐项遍历大小写不敏感匹配)。 |
|
||||
|
||||
### 2.2 IconEntry 结构体字段
|
||||
|
||||
每个 `IconEntry` 表示"当玩家的某个按键绑定在 `BindingPath` 时,应显示 `Icon` 这张图标"。
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `BindingPath` | `string` | Unity InputSystem 的**绑定路径**(Binding Path),格式为 `<设备类型>/<控件路径>`。例:`<Keyboard>/e`、`<Gamepad>/buttonSouth`。**查询时大小写不敏感**。 |
|
||||
| `Icon` | `Sprite` | 对应此绑定路径的按键图标。若为 `null`,`GetIcon()` 返回 `null`,UI 组件通常将图标区域隐藏。 |
|
||||
|
||||
> **⚠ 重要**:`BindingPath` 是玩家**当前实际绑定**的路径(含改键 `effectivePath`)。若玩家把「交互键」从 `<Keyboard>/e` 改到 `<Keyboard>/f`,系统查询的是 `<Keyboard>/f`,因此图标集中**需要包含全部玩家可能绑到的按键**,否则改键后图标显示为空。
|
||||
|
||||
---
|
||||
|
||||
## 三、Device Type 枚举说明
|
||||
|
||||
| 枚举值 | 含义 | 对应 InputIconService 字段 |
|
||||
|--------|------|--------------------------|
|
||||
| `KeyboardMouse` | 键盘 + 鼠标 | `_kbMouseSet` |
|
||||
| `XboxController` | Xbox 手柄(XInput)、PC 通用手柄 | `_xboxSet` |
|
||||
| `PlayStationController` | PS4 DualShock 4 / PS5 DualSense | `_playStationSet` |
|
||||
| `SwitchController` | Switch Pro Controller / Joy-Con | `_switchSet` |
|
||||
|
||||
`InputDeviceDetector` 通过 `InputSystem.IsFirstLayoutBasedOnSecond` 检测布局层次来精确识别设备类型:
|
||||
- DualShockGamepad / DualSenseGamepad → `PlayStationController`
|
||||
- XInputController → `XboxController`
|
||||
- 其他未知手柄 → 默认 `XboxController`(Xbox 图标最通用)
|
||||
|
||||
---
|
||||
|
||||
## 四、BindingPath 完整参考表
|
||||
|
||||
### 4.1 键鼠(KeyboardMouse)— 常用按键路径
|
||||
|
||||
| 按键 | BindingPath | 常见用途 |
|
||||
|------|-------------|---------|
|
||||
| E 键 | `<Keyboard>/e` | 交互(Interact) |
|
||||
| F 键 | `<Keyboard>/f` | 备用交互 / 拾取 |
|
||||
| R 键 | `<Keyboard>/r` | 技能 / 法术 |
|
||||
| 空格 | `<Keyboard>/space` | 跳跃(Jump) |
|
||||
| 左 Shift | `<Keyboard>/leftShift` | 冲刺(Dash)/ 行走 |
|
||||
| 左 Ctrl | `<Keyboard>/leftCtrl` | 下蹲 |
|
||||
| Q 键 | `<Keyboard>/q` | 技能槽 1 |
|
||||
| 1-4 数字键 | `<Keyboard>/1` … `<Keyboard>/4` | 技能快捷栏 |
|
||||
| Tab 键 | `<Keyboard>/tab` | 地图 / 物品栏 |
|
||||
| Esc 键 | `<Keyboard>/escape` | 暂停菜单 |
|
||||
| 鼠标左键 | `<Mouse>/leftButton` | 攻击(Attack) |
|
||||
| 鼠标右键 | `<Mouse>/rightButton` | 格挡 / 瞄准 |
|
||||
| 鼠标中键 | `<Mouse>/middleButton` | 特殊技能 |
|
||||
| 鼠标滚轮上 | `<Mouse>/scroll/up` | 切换武器 / 技能 |
|
||||
| 鼠标滚轮下 | `<Mouse>/scroll/down` | 切换武器 / 技能 |
|
||||
|
||||
> 完整键盘路径参考 Unity InputSystem 文档:[Keyboard Control Path](https://docs.unity3d.com/Packages/com.unity.inputsystem@latest/index.html?subfolder=/manual/Controls.html)
|
||||
|
||||
### 4.2 Xbox 手柄(XboxController)— 全按键路径
|
||||
|
||||
| 按键名称 | BindingPath | 说明 |
|
||||
|---------|-------------|------|
|
||||
| A 键(南键) | `<Gamepad>/buttonSouth` | 跳跃 / 确认 |
|
||||
| B 键(东键) | `<Gamepad>/buttonEast` | 冲刺 / 取消 |
|
||||
| X 键(西键) | `<Gamepad>/buttonWest` | 攻击 / 交互 |
|
||||
| Y 键(北键) | `<Gamepad>/buttonNorth` | 技能 / 特殊 |
|
||||
| LB(左肩键) | `<Gamepad>/leftShoulder` | 格挡 / 切换 |
|
||||
| RB(右肩键) | `<Gamepad>/rightShoulder` | 技能槽 / 切换 |
|
||||
| LT(左扳机) | `<Gamepad>/leftTrigger` | 蓄力攻击 / 瞄准 |
|
||||
| RT(右扳机) | `<Gamepad>/rightTrigger` | 攻击 / 确认大招 |
|
||||
| 左摇杆按下 | `<Gamepad>/leftStickButton` | 冲刺(长按) |
|
||||
| 右摇杆按下 | `<Gamepad>/rightStickButton` | 锁定目标 |
|
||||
| Select(菜单左) | `<Gamepad>/select` | 物品栏 |
|
||||
| Start(菜单右) | `<Gamepad>/start` | 暂停菜单 |
|
||||
| 十字键上 | `<Gamepad>/dpad/up` | 上方向 / 选择 |
|
||||
| 十字键下 | `<Gamepad>/dpad/down` | 下方向 / 选择 |
|
||||
| 十字键左 | `<Gamepad>/dpad/left` | 左方向 / 选择 |
|
||||
| 十字键右 | `<Gamepad>/dpad/right` | 右方向 / 选择 |
|
||||
| 左摇杆(上) | `<Gamepad>/leftStick/up` | 移动(上) |
|
||||
| 左摇杆(下) | `<Gamepad>/leftStick/down` | 移动(下) |
|
||||
|
||||
### 4.3 PlayStation 手柄
|
||||
|
||||
PS 手柄的**面板按键路径与 Xbox 完全相同**(`buttonSouth/East/West/North`)。底层 InputSystem 通过布局映射统一了方向标识:
|
||||
|
||||
| 逻辑路径 | Xbox 对应 | PlayStation 对应 |
|
||||
|---------|----------|----------------|
|
||||
| `buttonSouth` | A | ✕ Cross |
|
||||
| `buttonEast` | B | ○ Circle |
|
||||
| `buttonWest` | X | □ Square |
|
||||
| `buttonNorth` | Y | △ Triangle |
|
||||
| `leftShoulder` | LB | L1 |
|
||||
| `rightShoulder` | RB | R1 |
|
||||
| `leftTrigger` | LT | L2 |
|
||||
| `rightTrigger` | RT | R2 |
|
||||
| `select` | Select / View | Share / Create |
|
||||
| `start` | Start / Menu | Options |
|
||||
|
||||
> **关键设计点**:XboxController 和 PlayStationController 共享相同的 `BindingPath` 字符串,各自在**不同的 `InputDeviceIconSetSO`** 中映射到对应视觉风格的按键图标(Xbox 用圆形彩色图标,PS 用特殊符号图标),由 `InputIconService` 根据当前设备选择哪套 SO。
|
||||
|
||||
### 4.4 Switch 手柄
|
||||
|
||||
Switch Pro Controller 路径与 Xbox/PS 相同,面板按键按 Nintendo 习惯排列:
|
||||
|
||||
| 逻辑路径 | Switch 对应 |
|
||||
|---------|------------|
|
||||
| `buttonSouth` | B |
|
||||
| `buttonEast` | A |
|
||||
| `buttonWest` | Y |
|
||||
| `buttonNorth` | X |
|
||||
| `leftShoulder` | L |
|
||||
| `rightShoulder` | R |
|
||||
| `leftTrigger` | ZL |
|
||||
| `rightTrigger` | ZR |
|
||||
| `select` | - |
|
||||
| `start` | + |
|
||||
|
||||
> ⚠ **Switch 按键位置与 Xbox/PS 习惯相反**(南键是 B 不是 A),美术制作图标时需注意:
|
||||
> `buttonSouth` 图标应画 **B**(而非 A),`buttonEast` 图标应画 **A**(而非 B)。
|
||||
|
||||
---
|
||||
|
||||
## 五、图片(Sprite)规格要求
|
||||
|
||||
### 5.1 推荐尺寸
|
||||
|
||||
| 用途 | 推荐尺寸 | 说明 |
|
||||
|------|---------|------|
|
||||
| 标准按键图标(HUD/提示 UI) | **32×32 px** | InteractPromptWidget 默认显示尺寸,32px 在像素风格下清晰无锯齿 |
|
||||
| 高分辨率版本(设置界面、教程) | **64×64 px** | 用于放大显示的场合,需额外维护一套 |
|
||||
| 复合按键图标(LT+RT、双摇杆) | **48×24 px** 或 **64×32 px** | 横向组合按键,宽高比 2:1 |
|
||||
|
||||
### 5.2 Import Settings(Unity Inspector)
|
||||
|
||||
| 设置项 | 推荐值 | 说明 |
|
||||
|-------|-------|------|
|
||||
| Texture Type | `Sprite (2D and UI)` | 必须设置为 Sprite 类型,否则无法拖入 ObjectField |
|
||||
| Sprite Mode | `Single` | 每个按键一张独立图片,避免拆分 |
|
||||
| Pixels Per Unit | `32` | 与项目统一 PPU,1 像素 = 1/32 unit |
|
||||
| Filter Mode | `Point (no filter)` | 像素风格固定值,避免双线性插值导致模糊 |
|
||||
| Compression | `None`(开发),发布时 `ASTC 6x6`(移动端)| UI 图标质量要求高,开发期不压缩 |
|
||||
| Generate Mip Maps | `关闭` | 2D UI 不需要 Mip Maps |
|
||||
| Read/Write Enabled | `关闭` | 不需要像素读写 |
|
||||
| Max Size | `128` | 32px 图标不需要超过 128 |
|
||||
| Wrap Mode | `Clamp` | 避免边缘溢出 |
|
||||
|
||||
### 5.3 美术风格规范
|
||||
|
||||
| 规范项 | 说明 |
|
||||
|-------|------|
|
||||
| **背景透明** | 必须使用 PNG 格式,透明通道保存完整,不要有白色/黑色底边 |
|
||||
| **视觉安全区** | 图标主体保留 2px 内边距,避免内容贴近边缘被裁剪 |
|
||||
| **明度/对比度** | 图标应在深色(`rgba(0,0,0,0.85)`)背景上清晰可见;避免使用纯黑色线条(改用深灰 `#222`) |
|
||||
| **键鼠图标风格** | 偏向拟物,键盘按键绘制带圆角的方形按键轮廓,鼠标按键绘制鼠标轮廓 |
|
||||
| **手柄图标风格** | 手柄按键使用品牌标准配色:Xbox(A=绿、B=红、X=蓝、Y=黄),PS(✕=蓝、○=红、□=粉、△=绿),Switch 使用黑底圆形字母 |
|
||||
| **一致性** | 同一设备下所有图标使用相同的线条粗细、阴影效果、发光效果 |
|
||||
|
||||
### 5.4 文件命名规范
|
||||
|
||||
格式:`IC_Key_{DeviceShort}_{KeyName}.png`
|
||||
|
||||
| 示例路径 | 对应按键 |
|
||||
|---------|---------|
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_KBM_E.png` | 键盘 E 键 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_KBM_Space.png` | 键盘空格键 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_KBM_LMB.png` | 鼠标左键 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_KBM_RMB.png` | 鼠标右键 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_Xbox_A.png` | Xbox A 键 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_Xbox_RT.png` | Xbox RT 扳机 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_PS_Cross.png` | PS ✕ 键 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_PS_R2.png` | PS R2 扳机 |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_Switch_B.png` | Switch B 键(南键) |
|
||||
| `_Game/Art/UI/Icons/InputKeys/IC_Key_Switch_ZR.png` | Switch ZR 扳机 |
|
||||
|
||||
---
|
||||
|
||||
## 六、InputIconService 绑定配置
|
||||
|
||||
`InputIconService` 是图标集的运行时持有者,挂载在 Persistent 场景的 UIRoot 上。其 Inspector 字段:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `_inputReader` | `InputReaderSO` | 用于查询 Action 的绑定路径(`GetActionEffectivePath`) |
|
||||
| `_kbMouseSet` | `InputDeviceIconSetSO` | **键鼠图标集**,当检测到键盘/鼠标输入时激活 |
|
||||
| `_xboxSet` | `InputDeviceIconSetSO` | **Xbox 图标集**,检测到 XInput 手柄时激活;未配置时自动 fallback 至 `_kbMouseSet` |
|
||||
| `_playStationSet` | `InputDeviceIconSetSO` | **PlayStation 图标集**,检测到 DualShock/DualSense 时激活;未配置时 fallback 至 `_kbMouseSet` |
|
||||
| `_switchSet` | `InputDeviceIconSetSO` | **Switch 图标集**,检测到 Switch Pro/Joy-Con 时激活;未配置时 fallback 至 `_kbMouseSet` |
|
||||
| `_onDeviceChanged` | `InputDeviceTypeEventChannelSO` | 设备切换事件频道(`EVT_InputDeviceChanged.asset`),与 `InputDeviceDetector` 共用 |
|
||||
|
||||
> **Fallback 策略**:若对应设备图标集为 `null`,自动 fallback 至键鼠集。这意味着开发初期只配置 `_kbMouseSet` 即可正常运行,手柄图标集可后续补充,不影响功能。
|
||||
|
||||
---
|
||||
|
||||
## 七、UI 消费组件说明
|
||||
|
||||
### 7.1 InteractPromptWidget(按键提示 HUD)
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|-------|------|
|
||||
| `_promptChannel` | 引用 `InteractPromptEventChannelSO`,订阅 `InteractableDetector` 的广播 |
|
||||
| 显示逻辑 | 收到事件后查询 `IInputIconService.GetActionIcon(actionName)`,设置图标 Sprite;若图标为 `null` 则隐藏图标容器,仅显示文字 |
|
||||
| 刷新时机 | 设备切换(`OnIconSetChanged`)、改键(`BoundControlsChanged`)时自动重绘 |
|
||||
|
||||
### 7.2 InputIconImage(动态图标 Image 组件)
|
||||
|
||||
`InputIconImage` 是挂载在任意 `Image` 组件旁的辅助脚本,通过 `ServiceLocator` 获取 `IInputIconService`,支持两种工作模式:
|
||||
|
||||
| LookupMode | 说明 |
|
||||
|-----------|------|
|
||||
| `ByActionName` | **推荐**。指定 Action 名称(如 `"Interact"`、`"Jump"`),自动查询当前设备+改键后的有效图标 |
|
||||
| `ByBindingPath` | 固定路径,不随改键变化。适用于「始终显示空格键图标」等特定场景 |
|
||||
|
||||
### 7.3 InputDeviceIconSwitcher(静态图标切换)
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `_kbmSprite` | 键鼠时显示的 Sprite |
|
||||
| `_xboxSprite` | Xbox 手柄时显示的 Sprite |
|
||||
| `_psSprite` | PS 手柄时显示的 Sprite |
|
||||
| `_switchSprite` | Switch 手柄时显示的 Sprite |
|
||||
|
||||
适用于「图标固定、仅需在设备间切换整套外观」的场景(如教程截图、设置界面设备标识)。
|
||||
**不支持改键响应**,如需改键后自动更新请用 `InputIconImage`(ByActionName 模式)。
|
||||
|
||||
---
|
||||
|
||||
## 八、完整配置工作流
|
||||
|
||||
### 8.1 快速开始(最小可用配置)
|
||||
|
||||
```
|
||||
1. 准备图片
|
||||
放入 _Game/Art/UI/Icons/InputKeys/
|
||||
至少准备以下按键(根据实际绑定按需增删):
|
||||
键鼠:IC_Key_KBM_E.png(交互)、IC_Key_KBM_Space.png(跳跃)、IC_Key_KBM_LMB.png(攻击)
|
||||
Xbox:IC_Key_Xbox_X.png(交互)、IC_Key_Xbox_A.png(跳跃)、IC_Key_Xbox_RT.png(攻击)
|
||||
|
||||
2. 创建图标集 SO
|
||||
菜单 BaseGames/Input Icon Studio → 选择键鼠标签页 → 点击「指定图标集」→「新建...」
|
||||
保存至 _Game/Data/UI/InputIcons/ICN_KeyboardMouse.asset
|
||||
重复创建 ICN_Xbox.asset
|
||||
|
||||
3. 填充映射
|
||||
在 Input Icon Studio 中:
|
||||
a. 左侧选中 Action(如 Interact)
|
||||
b. 右侧确认 BindingPath(如 <Keyboard>/e)
|
||||
c. 将 IC_Key_KBM_E.png 拖入 Sprite 字段
|
||||
d. 切换到 Xbox 标签,重复上述步骤
|
||||
|
||||
4. 绑定到 InputIconService
|
||||
在 Persistent 场景 UIRoot → InputIconService Inspector 中:
|
||||
将 ICN_KeyboardMouse.asset 拖入 _kbMouseSet 字段
|
||||
将 ICN_Xbox.asset 拖入 _xboxSet 字段
|
||||
|
||||
5. 验证
|
||||
进入 PlayMode → 按 E 键 → 观察 HUD 交互提示出现键盘图标
|
||||
连接手柄 → 观察图标自动切换为 Xbox 图标
|
||||
```
|
||||
|
||||
### 8.2 批量填充工作流(大量按键)
|
||||
|
||||
```
|
||||
1. 在 ICN_KeyboardMouse.asset 的 Inspector 中:
|
||||
点击「从 Action Asset 填充路径」
|
||||
→ 自动为 Gameplay ActionMap 中所有 Keyboard&Mouse 绑定生成 Entry(路径已填入,Icon 为空)
|
||||
|
||||
2. 将对应 Sprite 批量拖入各 Entry 的 Icon 字段
|
||||
(可用 Input Icon Studio 左列的覆盖率指示点确认进度)
|
||||
|
||||
3. 在 Input Icon Studio 查看总覆盖率:
|
||||
标签栏显示 "🖱 键鼠 N/N" — N/N 表示全部配置完成
|
||||
```
|
||||
|
||||
### 8.3 改键适配说明
|
||||
|
||||
**图标集应包含玩家可能绑定到的所有按键**,而非仅包含默认绑定。
|
||||
|
||||
例如交互键默认为 `<Keyboard>/e`,若玩家将其改为 `<Keyboard>/f`,系统查询 `<Keyboard>/f`,图标集中需有该条目才能正确显示。
|
||||
|
||||
**推荐策略**:为键盘图标集预填充全部 26 个字母键 + 常用功能键,为手柄图标集预填充所有面板按键和扳机键。
|
||||
|
||||
---
|
||||
|
||||
## 九、调试与常见问题排查
|
||||
|
||||
| 现象 | 原因 | 解决方案 |
|
||||
|------|------|---------|
|
||||
| 图标区域不显示(空白/隐藏) | `BindingPath` 未在图标集中找到匹配条目 | 在 Input Icon Studio 确认该 Action 当前绑定路径,并在图标集中添加对应条目 |
|
||||
| 切换设备后图标没有变化 | `InputDeviceDetector` 或 `InputIconService` 未在场景中激活 | 确认 Persistent 场景 UIRoot 上挂载了两个组件,且 `_onDeviceChanged` 字段引用正确 |
|
||||
| 改键后图标仍显示旧按键 | 使用的是 `InputDeviceIconSwitcher` 而非 `InputIconImage(ByActionName)` | 改用 `InputIconImage` 组件并设置 `LookupMode = ByActionName` |
|
||||
| 所有设备均显示键鼠图标 | 手柄图标集字段为 null,触发了 fallback 逻辑 | 在 InputIconService Inspector 中为手柄字段指定对应 SO |
|
||||
| 图标显示模糊 | Import Settings 的 Filter Mode 不正确 | 将所有按键图标的 Filter Mode 改为 `Point (no filter)` |
|
||||
| 图标有白色边缘 | 导出时 PNG 透明通道处理不正确 | 用 Photoshop/Aseprite 重新导出,确保「直接 Alpha」(Straight Alpha)而非预乘 Alpha |
|
||||
| 手柄图标显示 Xbox 风格,但玩家用的是 PS 手柄 | `InputDeviceDetector` 未能识别 DualShock 布局 | 确保 Input System 包含 PS 设备支持(`com.unity.inputsystem` ≥ 1.4),并在 Player Settings 中勾选 DualShock 支持 |
|
||||
| Input Icon Studio 左列 Action 为空 | `InputReaderSO` 未填入,或 `_inputActions` 字段名不匹配 | 在工具栏 InputReaderSO 字段指定资产;若字段名有变更,同步更新 `InputIconStudioWindow.ReloadActionAsset()` 中的 `FindProperty("_inputActions")` |
|
||||
|
||||
---
|
||||
|
||||
## 十、推荐图标集最小条目清单
|
||||
|
||||
以下是按项目实际 Gameplay ActionMap 中的 Actions 推荐配置的最小图标集。
|
||||
|
||||
### 10.1 键鼠图标集 — ICN_KeyboardMouse
|
||||
|
||||
| Action 名称 | 默认 BindingPath | 建议图标 |
|
||||
|------------|-----------------|---------|
|
||||
| Move(上) | `<Keyboard>/w` | W键图标 |
|
||||
| Move(下) | `<Keyboard>/s` | S键图标 |
|
||||
| Move(左) | `<Keyboard>/a` | A键图标 |
|
||||
| Move(右) | `<Keyboard>/d` | D键图标 |
|
||||
| Jump | `<Keyboard>/space` | 空格键图标 |
|
||||
| Dash | `<Keyboard>/leftShift` | Shift键图标 |
|
||||
| Attack | `<Mouse>/leftButton` | 鼠标左键图标 |
|
||||
| Interact | `<Keyboard>/e` | E键图标 |
|
||||
| Map | `<Keyboard>/m` | M键图标 |
|
||||
| Pause | `<Keyboard>/escape` | Esc键图标 |
|
||||
|
||||
### 10.2 Xbox 手柄图标集 — ICN_Xbox
|
||||
|
||||
| Action 名称 | BindingPath | 建议图标 |
|
||||
|------------|-------------|---------|
|
||||
| Jump | `<Gamepad>/buttonSouth` | A键图标(绿) |
|
||||
| Dash | `<Gamepad>/buttonEast` | B键图标(红) |
|
||||
| Attack | `<Gamepad>/rightTrigger` | RT图标 |
|
||||
| Interact | `<Gamepad>/buttonWest` | X键图标(蓝) |
|
||||
| Map | `<Gamepad>/select` | View/Select图标 |
|
||||
| Pause | `<Gamepad>/start` | Menu/Start图标 |
|
||||
|
||||
---
|
||||
|
||||
## 十一、修改历史
|
||||
|
||||
| 日期 | 修改内容 |
|
||||
|------|---------|
|
||||
| 2026-05-22 | 初版:完整字段说明、BindingPath 参考表、图片规格要求、工作流及排查指南 |
|
||||
549
Docs/Tuning/InputDeviceIconSet_Tuning.md
Normal file
549
Docs/Tuning/InputDeviceIconSet_Tuning.md
Normal file
@@ -0,0 +1,549 @@
|
||||
# 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. **改键后路径会变化**:例如玩家将「跳跃」从 `<Keyboard>/space` 改为 `<Keyboard>/leftShift`,系统会查询 `<Keyboard>/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 |
|
||||
|------|-------------|
|
||||
| 空格键 | `<Keyboard>/space` |
|
||||
| E 键(交互默认) | `<Keyboard>/e` |
|
||||
| F 键 | `<Keyboard>/f` |
|
||||
| R 键 | `<Keyboard>/r` |
|
||||
| Shift 键(左) | `<Keyboard>/leftShift` |
|
||||
| Ctrl 键(左) | `<Keyboard>/leftCtrl` |
|
||||
| Tab 键 | `<Keyboard>/tab` |
|
||||
| Escape 键 | `<Keyboard>/escape` |
|
||||
| Enter 键 | `<Keyboard>/enter` |
|
||||
| 方向键上 | `<Keyboard>/upArrow` |
|
||||
| 方向键下 | `<Keyboard>/downArrow` |
|
||||
| 方向键左 | `<Keyboard>/leftArrow` |
|
||||
| 方向键右 | `<Keyboard>/rightArrow` |
|
||||
| W / A / S / D | `<Keyboard>/w` · `<Keyboard>/a` · `<Keyboard>/s` · `<Keyboard>/d` |
|
||||
| 数字键 1~4 | `<Keyboard>/1` ~ `<Keyboard>/4` |
|
||||
| 鼠标左键 | `<Mouse>/leftButton` |
|
||||
| 鼠标右键 | `<Mouse>/rightButton` |
|
||||
| 鼠标中键 | `<Mouse>/middleButton` |
|
||||
| 滚轮向上 | `<Mouse>/scroll/up` |
|
||||
| 滚轮向下 | `<Mouse>/scroll/down` |
|
||||
|
||||
### 3.2 Xbox / XInput 手柄路径(`ICN_Xbox.asset`)
|
||||
|
||||
| 描述 | BindingPath |
|
||||
|------|-------------|
|
||||
| A 键(南方键,交互默认) | `<Gamepad>/buttonSouth` |
|
||||
| B 键(东方键) | `<Gamepad>/buttonEast` |
|
||||
| X 键(西方键) | `<Gamepad>/buttonWest` |
|
||||
| Y 键(北方键) | `<Gamepad>/buttonNorth` |
|
||||
| 左摇杆按下 | `<Gamepad>/leftStickButton` |
|
||||
| 右摇杆按下 | `<Gamepad>/rightStickButton` |
|
||||
| 左肩键 LB | `<Gamepad>/leftShoulder` |
|
||||
| 右肩键 RB | `<Gamepad>/rightShoulder` |
|
||||
| 左扳机 LT | `<Gamepad>/leftTrigger` |
|
||||
| 右扳机 RT | `<Gamepad>/rightTrigger` |
|
||||
| 十字键上 | `<Gamepad>/dpad/up` |
|
||||
| 十字键下 | `<Gamepad>/dpad/down` |
|
||||
| 十字键左 | `<Gamepad>/dpad/left` |
|
||||
| 十字键右 | `<Gamepad>/dpad/right` |
|
||||
| 开始键 Start / Menu | `<Gamepad>/start` |
|
||||
| 选择键 Select / View | `<Gamepad>/select` |
|
||||
| 左摇杆方向 | `<Gamepad>/leftStick` |
|
||||
| 右摇杆方向 | `<Gamepad>/rightStick` |
|
||||
|
||||
### 3.3 PlayStation 手柄路径(`ICN_PlayStation.asset`)
|
||||
|
||||
> **路径与 Xbox 完全相同**(均使用通用 `<Gamepad>` 路径),只有图标 Sprite 不同。
|
||||
> PlayStation 的按键物理布局与 Xbox 一致(南/东/西/北方键),区别在于图标(✕ / ○ / □ / △ vs A/B/X/Y)。
|
||||
|
||||
| 描述 | PS 图标 | BindingPath(与 Xbox 相同) |
|
||||
|------|---------|--------------------------|
|
||||
| 南方键 Cross(✕) | ✕ 图标 | `<Gamepad>/buttonSouth` |
|
||||
| 东方键 Circle(○) | ○ 图标 | `<Gamepad>/buttonEast` |
|
||||
| 西方键 Square(□) | □ 图标 | `<Gamepad>/buttonWest` |
|
||||
| 北方键 Triangle(△) | △ 图标 | `<Gamepad>/buttonNorth` |
|
||||
| L1 | L1 图标 | `<Gamepad>/leftShoulder` |
|
||||
| R1 | R1 图标 | `<Gamepad>/rightShoulder` |
|
||||
| L2 | L2 图标 | `<Gamepad>/leftTrigger` |
|
||||
| R2 | R2 图标 | `<Gamepad>/rightTrigger` |
|
||||
| L3(左摇杆按下)| L3 图标 | `<Gamepad>/leftStickButton` |
|
||||
| R3(右摇杆按下)| R3 图标 | `<Gamepad>/rightStickButton` |
|
||||
| Options 键 | Options 图标 | `<Gamepad>/start` |
|
||||
| TouchPad / Share | TouchPad 图标 | `<Gamepad>/select` |
|
||||
|
||||
### 3.4 Nintendo Switch 手柄路径(`ICN_Switch.asset`)
|
||||
|
||||
> **路径同样与 Xbox/PS 共用 `<Gamepad>` 路径**,仅图标不同。
|
||||
> Switch 的南方键是 B,东方键是 A,与 Xbox 方向相反,务必使用正确的 Switch 图标。
|
||||
|
||||
| 描述 | Switch 图标 | BindingPath |
|
||||
|------|------------|-------------|
|
||||
| 南方键 B | B 图标 | `<Gamepad>/buttonSouth` |
|
||||
| 东方键 A | A 图标 | `<Gamepad>/buttonEast` |
|
||||
| 西方键 Y | Y 图标 | `<Gamepad>/buttonWest` |
|
||||
| 北方键 X | X 图标 | `<Gamepad>/buttonNorth` |
|
||||
| L 键 | L 图标 | `<Gamepad>/leftShoulder` |
|
||||
| R 键 | R 图标 | `<Gamepad>/rightShoulder` |
|
||||
| ZL 键 | ZL 图标 | `<Gamepad>/leftTrigger` |
|
||||
| ZR 键 | ZR 图标 | `<Gamepad>/rightTrigger` |
|
||||
| + 键 | + 图标 | `<Gamepad>/start` |
|
||||
| - 键 | - 图标 | `<Gamepad>/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 ← <Keyboard>/space
|
||||
IC_Key_KBM_E.png ← <Keyboard>/e
|
||||
IC_Key_KBM_LMB.png ← <Mouse>/leftButton
|
||||
IC_Key_Xbox_South.png ← <Gamepad>/buttonSouth (A键)
|
||||
IC_Key_Xbox_RT.png ← <Gamepad>/rightTrigger
|
||||
IC_Key_PS_Cross.png ← <Gamepad>/buttonSouth (✕键)
|
||||
IC_Key_PS_R2.png ← <Gamepad>/rightTrigger
|
||||
IC_Key_Switch_South.png ← <Gamepad>/buttonSouth (B键)
|
||||
IC_Key_Switch_ZR.png ← <Gamepad>/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` 时,手柄路径(如 `<Gamepad>/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 模式**:填写固定路径(如 `<Keyboard>/space`),不跟随改键 |
|
||||
|
||||
### 8.2 LookupMode 枚举
|
||||
|
||||
| 枚举值 | 适用场景 | 改键响应 | 设备切换响应 |
|
||||
|--------|---------|---------|------------|
|
||||
| `ByActionName`(推荐)| 所有正常游戏内 UI 提示 | ✅ 自动更新 | ✅ 自动切换 |
|
||||
| `ByBindingPath` | 教程截图说明、固定按键展示(如「按 Space 确认」这类静态文案)| ❌ 不更新 | ❌ 不切换 |
|
||||
|
||||
> `ByBindingPath` 模式目前图标查询功能为低优先级,实际返回 null(`Image.enabled = false`)。如需支持,可在 `InputIconService` 中通过 `GetOrDefault<IInputIconService>()` + `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` 中包含改键后目标按键的路径(如玩家改到 `<Keyboard>/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` |
|
||||
@@ -11,6 +11,8 @@
|
||||
| 文件 | 覆盖系统 |
|
||||
|---|---|
|
||||
| [PlayerJumpDash_Tuning.md](PlayerJumpDash_Tuning.md) | 玩家跳跃 / 冲刺手感参数 |
|
||||
| [WeaponSO_Tuning.md](WeaponSO_Tuning.md) | 武器连击 / 伤害 / HitBox 参数 |
|
||||
| [InputDeviceIconSet_Tuning.md](InputDeviceIconSet_Tuning.md) | 按键图标集 SO 配置、BindingPath 参考表、图片规格、完整工作流 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user