Files
zeling_v2/Docs/Design/75_MenuLayoutRemodelPlan.md
2026-06-08 11:26:17 +08:00

198 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 75 · 菜单布局与操作逻辑对照 + 改造方案
> 目标:将暂停 / 背包 / 地图 / 护符 / 能力等游戏内菜单的**组成布局逻辑**与**打开-关闭-切换操作逻辑**,对齐业界横版动作冒险标杆作的交互范式,同时**保留本项目独有玩法**(三形态切换、形态下的魂技能 / 魄技能、无"工具(Tools)"系统)。
>
> 本文档只定义信息架构与交互契约,不照搬任何标杆作的玩法系统。
> 命名 / 目录 / Addressable / Layer 一律遵守 `Docs/Standards/`;所有搭建走 `Assets/_Game/Scripts/Editor` 脚手架,不裸建。
相关文档:`Docs/Design/10_UISystem.md``Docs/Design/74_UIScreenFlowDocument.md``Docs/Design/16_MapSystem.md``Docs/DesignSpec/06_FormSystem.md``Docs/DesignSpec/10_UISystem.md`
---
## 0. 一句话结论
架构已到位统一导航栈、L/R 切 Tab、暗雾地图、确认弹窗、数据驱动配置都有。差距在**信息架构**:当前存在"暂停按钮菜单"与"背包 Tab Hub"两条并行入口、内容重叠;目标是把游戏内一切**查看/装备类**面板收敛进**统一 Tab 屏**,暂停退化为薄覆盖层。再补一个缺失的**图鉴**面板。本质是**收敛接线 + 补面板**,新代码很少。
---
## 1. 对标范围界定
| 维度 | 是否参考标杆 | 说明 |
|---|---|---|
| 菜单**布局结构**Tab 划分、层级) | ✅ 参考 | 一键进入带 Tab 的统一屏 |
| **操作逻辑**(开/关/切 Tab/回退/焦点) | ✅ 参考 | 同键开关、L/R 切页、B 逐层退、手柄全程可达 |
| **地图**面板形态 | ✅ 完全参考 | 暗雾、Pin、传送、缩放居中 |
| 玩法系统(护符/工具/资源) | ❌ 用本项目自有 | 无 Tools护符保持现有凹槽模型资源为灵力/魄元而非"丝/念珠" |
| 技能呈现 | 本项目原创 | 三形态 × 魂技能/魄技能,标杆作无此概念,作为独立 Tab 承载 |
---
## 2. 当前实现现状(事实基线)
### 2.1 两条入口
| 入口 | 触发链 | 落点 |
|---|---|---|
| **暂停** | Gameplay `Pause` Action → `EVT_PauseRequested``UIManager.TogglePause()``OpenPanel(PanelId.Pause)` | `DataDrivenPauseMenuController`(竖排按钮,数据驱动) |
| **背包** | Gameplay `Inventory` Action → `EVT_InventoryOpen``OpenPanel(PanelId.Inventory)` | `InventoryHubPanel`Tab HubL/R 肩键切页) |
| 地图(独立) | `EVT_MapOpen` / `EVT_FastTravelOpen``OpenPanel(PanelId.Map)` | `MapPanel`(独立面板,**不在 Hub 内** |
| 护符(独立) | `EVT_CharmPanelOpen``OpenPanel(PanelId.CharmPanel)` | `CharmEquipPanel`(独立面板) |
**问题**:暂停菜单的按钮可用 `PauseMenuAction.OpenPanel``FormSkills / Abilities / Map`;而这些又能作为 Hub 的 Tab。**同一内容两套入口、两种布局**,是与标杆范式最大的结构偏差。
### 2.2 已有面板与 PanelId
`PanelId``UIManager.cs``Pause, Settings, Map, Shop, CharmPanel, SpellSelect, Inventory, FormSkills, Abilities`
| 面板 | 脚本 | 现状 |
|---|---|---|
| 暂停 | `Menus/DataDrivenPauseMenuController.cs` | ✅ 数据驱动 |
| 背包 Hub | `Inventory/InventoryHubPanel.cs` | ✅ Tab 容器(注释规划 Map/Inventory/Tools/Journal/Quests/Options |
| 物品 | `Inventory/ItemInventoryPanel.cs` | ✅ 网格+详情(仅展示) |
| 任务 | `Inventory/QuestLogPanel.cs` | ✅ 存在 |
| 护符 | `CharmEquipPanel.cs` + `CharmCardView.cs` | ✅ 凹槽装备 |
| 地图 | `World/Map/MapPanel.cs` | ✅ 暗雾/Pin/传送/定位器门控 |
| 形态技能 | `FormSkillPanel.cs` | ✅ 三形态 × 魂/魄(只读) |
| 能力总览 | `DataDrivenAbilityPanel.cs` + `AbilityCellView.cs` | ✅ 数据驱动解锁态 |
| 设置 | `Settings/DataDrivenSettingsPanel.cs` | ✅ 数据驱动 |
| **图鉴(Bestiary)** | — | ❌ **缺失** |
### 2.3 已具备的操作逻辑(无需重做)
- 统一导航栈 `UINavigator`Push/Pop、焦点保存恢复、Modal 屏蔽下层、场景卸载清栈。
- 取消归口UI map `Cancel`ESC / 手柄 B`EVT_UICancelPressed` → 导航器关栈顶一层。
- Tab 切换:`InventoryHubPanel` 监听 `EVT_InventoryTabNext/Prev`UI map 肩键)+ 头部按钮点击;焦点委托给 Tab 内容(若实现 `IFocusable`)。
- 地图专用键:`CycleMinimapZoom``MapCenter`
---
## 3. 标杆范式要点(交互参考,去玩法)
1. **单键进统一屏**:一个键打开带横向 Tab 的菜单屏同键再按关闭toggle
2. **L/R 肩键循环 Tab**Tab 头显示名称 + 肩键提示字形(随输入设备切换 KB/手柄图标)。
3. **地图可独立直达**:地图键直接打开"统一屏并定位到地图 Tab"。
4. **B/Circle/ESC 逐层回退**:先关子详情,再关整屏。
5. **暂停是薄覆盖**:游戏冻结、半透明,仅 Resume / Options / Return / Quit**不承载查看类面板**。
6. **手柄全程可达**:每个 Tab/列表进入即有默认焦点。
---
## 4. 逐项对照(符合度)
| 范式要点 | 当前 | 符合度 | 差距 |
|---|---|---|---|
| 单键进统一 Tab 屏 | 有 Hub但内容也散落在暂停菜单 | ⚠️ 部分 | 入口重叠,需收敛 |
| 同键 toggle 关闭 | `OpenInventory` 只 Push 不 toggle | ⚠️ 部分 | 缺再按关闭 |
| L/R 切 Tab + 头部字形提示 | L/R 已有;字形提示未确认 | ⚠️ 部分 | Tab 头补设备图标提示 |
| 地图键直达地图 Tab | 地图是**独立面板**,与 Hub 并行 | ❌ 不符 | 地图应作为 Tab地图键打开 Hub 并选中地图 Tab |
| B/ESC 逐层回退 | `UINavigator` 已实现 | ✅ 符合 | — |
| 暂停薄覆盖、不含查看面板 | 暂停菜单含 `OpenPanel` 跳转项 | ❌ 不符 | 移除跳转项,仅留系统操作 |
| 手柄全程焦点 | 基类已支持,逐面板需核 | ⚠️ 部分 | 各 Tab 内容补 `IFocusable` |
| 护符/装备 | 凹槽模型(本项目自有) | ✅ 按本项目算符合 | 仅作 Tab 收编 |
| 形态技能(魂/魄) | 独立面板(本项目自有) | ✅ 符合 | 作 Tab 收编 |
| 地图形态 | 暗雾/Pin/传送/定位器门控 | ✅ 高度符合 | 仅缺快旅历史(可选) |
| 图鉴 Bestiary | 无 | ❌ 缺失 | 新建面板 + Tab |
---
## 5. 目标信息架构
### 5.1 统一 Tab 屏(`InventoryHubPanel`PanelId.Inventory
Tab 顺序(结合本项目内容,"工具"位由"形态技能"承载):
| # | Tab | 承载面板 | 备注 |
|---|---|---|---|
| 1 | 地图 | `MapPanel` | 由独立面板**收编为 Tab**;地图键直达此 Tab |
| 2 | 形态技能 | `FormSkillPanel` | 三形态 × 魂/魄(本项目核心,取代标杆"工具"位) |
| 3 | 能力 | `DataDrivenAbilityPanel` | 解锁总览 |
| 4 | 护符 | `CharmEquipPanel` | 凹槽装备(收编为 Tab |
| 5 | 物品 | `ItemInventoryPanel` | 收藏/材料/关键道具 |
| 6 | 任务 | `QuestLogPanel` | NPC 任务日志 |
| 7 | 图鉴 | `BestiaryPanel`**新建** | 击杀解锁敌人条目 |
> Tab 数量可裁剪;至少 1/2/4/5 为首发必备3/6/7 视进度排期。
### 5.2 暂停薄覆盖(`DataDrivenPauseMenuController`PanelId.Pause
仅保留系统级动作,**删除一切 `OpenPanel` 查看类跳转**
| 项 | Action |
|---|---|
| 继续 | `Resume` |
| 选项 | `OpenSettings` |
| 返回主菜单 | `ReturnToMainMenu` |
| 退出 | `Quit` |
### 5.3 入口操作契约
| 输入 | 行为 |
|---|---|
| `Inventory` 键 | 打开统一屏(回上次 Tab已开则关闭toggle |
| 地图键(`EVT_MapOpen`/`EVT_FastTravelOpen` | 打开统一屏并选中**地图 Tab** |
| `InventoryTabNext/Prev`L/R 肩键) | 在统一屏内循环 Tab |
| `Pause`Start | 打开暂停薄覆盖(独立,不与统一屏共栈语义) |
| `Cancel`ESC/B | 导航器关栈顶一层(子详情→整屏) |
---
## 6. 改造方案(分阶段)
> 全程走脚手架;改完跑第 8 节验证。
### 阶段 A — 收敛入口职责(低风险,主要是配置)
1. **精简暂停配置** `Assets/_Game/Data/UI/UI_PauseMenuConfig.asset`:删除 `FormSkills/Abilities/Map``OpenPanel` 项,仅留 Resume/Settings/ReturnToMainMenu/Quit。
2. **背包键 toggle**:在 `UIManager``OpenInventory()` 增加 toggle参照现有 `TogglePause()` 模式:栈顶若为 Inventory 则 `Pop`,否则 `OpenPanel`)。
3. **地图键直达地图 Tab**:将 `EVT_MapOpen`/`EVT_FastTravelOpen` 改为"打开 Inventory Hub 并选中地图 Tab"。建议给 `InventoryHubPanel``OpenAtTab(int)` / 增一个 `IntEventChannelSO`(如 `EVT_InventoryOpenAtTab``UIManager.OpenMap()` 打开 Hub 后请求选中地图 Tab。
- 保留 `MapPanel` 独立 PanelId 与否由"地图是否需脱离 Hub 全屏"决定(见第 9 节待决)。
### 阶段 B — 面板收编为 Tab用脚手架重建 Hub 预制件)
4. **扩建 `UI_InventoryHub` 预制件**:用 `InventoryHubScaffoldWizard.ScaffoldInventoryHub`(或现有 Hub 脚手架)把 5.1 的面板逐个挂为 `TabEntry.content`,配 `headerButton` + `headerHighlight`,按 5.1 顺序排列。
- 各 Tab 内容根需实现 `IFocusable`(或保证内部首项可聚焦),以便切 Tab 自动接管焦点。
- 地图 / 护符既有独立 PanelId 的,改为**实例复用**:要么 Tab 内嵌同一面板预制,要么 Hub 内 Tab 与独立 PanelId 指向同一 root二选一避免双实例见待决
5. **Tab 头字形提示**Tab 条左右加 `InputIconImage` / `InputDeviceIconSwitcher`,显示 L/R 肩键字形(随设备切换)。
### 阶段 C — 补图鉴(新面板)
6. **新建 `BestiaryPanel`**:仿 `DataDrivenAbilityPanel` 的数据驱动套路——`BestiaryEntrySO`/数据库 SO 列敌人条目,击杀解锁(订阅敌人死亡事件),网格 + 详情。先补对应 **Editor 脚手架**(参考 `UIAbilityOverviewScaffold``AssignReference` 绑定模式)再建预制件。
7. 注册为第 7 个 Tab数据源接 `Docs/Design/48_EnemyRoster.md` / 敌人数据库。
### 阶段 D — 打磨
8. 进出场动画统一Hub 已有滑入+淡入);暂停覆盖层半透明背板。
9. 逐 Tab 核手柄默认焦点;确认 `Cancel` 在"子详情打开时只退一层"。
---
## 7. 涉及改动清单(速查)
| 类型 | 对象 | 改动 |
|---|---|---|
| 资产 | `UI_PauseMenuConfig.asset` | 删跳转项 |
| 代码 | `UIManager.cs` | `OpenInventory` toggle`OpenMap` 改为开 Hub 定位地图 Tab |
| 代码 | `InventoryHubPanel.cs` | 增 `OpenAtTab(int)` + 监听 `EVT_InventoryOpenAtTab` |
| 事件 | 新增 `EVT_InventoryOpenAtTab`(Int) | 经 `CreateEventChannelAssets` 创建 |
| 预制件 | `UI_InventoryHub` | 经 Hub 脚手架挂全部 Tab + 字形提示 |
| 新建 | `BestiaryPanel` + SO + 脚手架 + 预制件 | 阶段 C |
| 可选 | `PanelId.Bestiary` | 若图鉴也需独立直达 |
---
## 8. 改造后自检(强制)
- `BaseGames/Tools/Validation/Validate All ScriptableObjects`
- `BaseGames/Addressables/Validate Address Keys`(新 SO/预制件地址常量化)
- `BaseGames/Tools/Maintenance/Physics2D Layer Matrix/Check`
- 运行期手测:背包键 toggle、L/R 切 7 个 Tab、地图键直达地图 Tab、暂停覆盖仅系统项、ESC 逐层退、全程手柄可达。
---
## 9. 待决问题
1. **地图双形态**:地图既作 Hub 的 Tab又是否保留可全屏脱离 Hub 的独立打开?(影响是否保留 `PanelId.Map` 双实例策略)
2. **首发 Tab 集**7 个是否全部首发,还是先上 地图/形态技能/护符/物品,能力·任务·图鉴二期?
3. **图鉴数据源**:解锁条件(首次击杀?需击杀 N 次解锁全条目?)与数据归属(敌人数据库 vs 独立 `BestiaryEntrySO`)。
4. **暂停与统一屏的栈关系**:是否允许在暂停覆盖里再开统一屏(一般不允许,二者互斥)。