Files
zeling_v2/Docs/Review/Minimap_Review_Round12_Independent.md
Joywayer f74d7f1877 Add independent review reports for Minimap system (Rounds 8, 9, and 26)
- Round 8 report highlights improvements in architecture, editor usability, and data robustness, with a total score of 80/100.
- Round 9 report focuses on editor extension capabilities, identifying issues with room data indexing and layout editing, resulting in a score of 76/100.
- Round 26 report evaluates the system against commercial standards, noting new issues and confirming previous fixes, with a score of 95.8/100.
2026-05-25 23:15:12 +08:00

204 lines
12 KiB
Markdown
Raw Permalink 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.
# Minimap 独立评估报告 — Round 12
**评估基线:** R11 全部 12 项修复N1N12已实现并验证InputSystem 迁移已完成
**前轮得分:** Round 11 — 85.6/100 (B+,含 12 项已知 findings)
**本轮目标:** 基于修复后的最新代码重新全面审查,发现新遗留问题并给出综合评分
---
## 评分总览
| 维度 | 权重 | 得分 | 上轮 |
|------|------|------|------|
| 架构与解耦 | 15% | 9.0 | 8.5 |
| 数据设计 | 15% | 8.0 | 8.0 |
| 运行时性能 | 20% | 8.8 | 8.5 |
| 编辑器工具 | 15% | 8.5 | 8.5 |
| 游戏功能完整性 | 15% | 7.5 | 7.5 |
| 代码质量 | 10% | 8.5 | 8.5 |
| 可扩展性 | 10% | 8.0 | 7.5 |
| **加权总分** | 100% | **86.2 / 100** | 85.6 |
**评级B+**R11 修复带来了小幅提升,当前剩余问题均为 P2/P3无 P1 阻断性缺陷)
---
## 维度详评
### 1. 架构与解耦 (9.0/10) ↑
**优点:**
- Interface-based IoC`IMapService` / `IPlayerPositionProvider` / `IPinService`,运行时零具体类耦合
- ServiceLocator 延迟获取,支持启动顺序不确定场景
- 事件语义分离:`OnDatabaseChanged`结构重建vs `OnExplorationChanged`(轻量刷新)
- R11-N1 修复后 `MinimapHUD` 双服务独立订阅守卫,避免重复注册
- `MapServiceExtensions` 扩展方法,对外暴露高层 API 而不污染接口定义
- `MapGridConstants` 统一共享常量,避免魔法数字分散
**遗留问题:**
- **N7 (P3)** `MapPanel.LateUpdate` 每帧调用 `SubscribeServices()` 直到三个服务都获取完毕,之后仍无法跳出该分支(缺少 `_servicesReady` 标志)。对热路径略有冗余
- **N8 (P3)** `MapPanel` 同时订阅 `_onMapUpdated` EventChannel 和 `IMapService.OnExplorationChanged`,两者功能部分重叠(单个房间发现时两者都会触发,导致 `OnExplorationChanged → RefreshAllCells``OnMapUpdated → cell.SetVisibility` 连续对同一格子执行两次刷新)
### 2. 数据设计 (8.0/10) →
**优点:**
- 三层可见度Unknown / Explored / Mapped标准 Metroidvania 分级
- `MapDatabaseSO` 双索引:`string→room` (O(1)) + `cell→roomId` 空间索引 (O(1))
- `RoomExitData` 字段完整ExitGridPos / Direction / TransitionType
- R11-N2/N11 修复了 `OnValidate` 延迟调用去重 + RoomId 自动 Trim + 特殊字符校验
**遗留问题:**
- **N5 (P2)** `RoomExitData.ExitGridPos``Vector2Int.zero` 作"未配置"哨兵,而 (0,0) 同时是合法格子坐标,语义二义性。编辑器中未配置出口位置时 `DrawExitLines` 回退到目标房间中心,但 (0,0 房间角落坐标) 与"未设置"无法区分,可能产生误判
*建议:增加 `bool HasCustomExitPos` 字段,或改用 `Vector2Int?` nullable明确区分*
- **N9 (P3)** `MapRoomDataSO` 用三个独立 bool 字段(`IsBossRoom` / `IsSavePoint` / `IsShop`)描述房间类型,每新增一类(如商人房、挑战房)需要改动 SO 类定义,扩展成本高
*建议:改为 `[Flags] enum RoomType` 或支持多值选择的枚举,单字段表达复合属性*
### 3. 运行时性能 (8.8/10) ↑
**优点:**
- R11-N5 `MinimapHUD` 新增 `Stack<MapRoomCellUI> _cellPool`ClearAllCells 回收、RefreshView 复用,彻底消除频繁 Instantiate/Destroy
- R11-N6 `MapManager.GetRoomsByRegion` 引入 `_regionCache`O(N) 全扫变 O(1)`NotifyDatabaseChanged` 时清缓存
- O(1) 空间索引用于玩家房间检测(`GetRoomIdAtCell`
- PinsVersion 脏检查避免无效 RenderPins
- `MapInputHandler` 缓存 `_navInput`Update 零轮询
- `_roomsInViewBuffer` / `_newlyAddedBuffer` / `_toRemove` 避免 MinimapHUD 刷新时分配
**遗留问题:**
- **N1 (P2)** `MapPanel.RebuildAll``OnDestroy` 对格子调用 `Destroy(cell.gameObject)``ClearExits` 对出口连接线调用 `Destroy(img.gameObject)`。与 `MinimapHUD``_cellPool` 模式不对称RebuildAll 在地图数据库变更时被调用,会产生 GC 脉冲
*建议:为 `MapPanel` 补充 `Stack<MapRoomCellUI> _cellPool` 和 `Stack<Image> _exitPool`ClearExits/RebuildAll 回收而非销毁*
- **N6 (P3)** `RegionNameDisplay.ResolveDisplayName``_regionNames` 数组做 `foreach` 线性搜索O(N))。每次进入新区域触发,通常 N 不超过 20 影响不大,但可在 `Awake` 预建 `Dictionary<string, RegionNameEntry>` 一劳永逸
- **N7 (P3)** 见架构章节LateUpdate 的 `SubscribeServices` 每帧空转
### 4. 编辑器工具 (8.5/10) →
**优点:**
- `MapLayoutEditorWindow`:全功能格子预览(缩放/平移/搜索/图例/Play Mode 玩家点)
- R11-N7 `OnProjectChange()` 清缓存 + Repaint资产刷新后立即同步
- `MapRoomDataEditor`Scene View 双角控制点拖拽 + Undo 支持
- `MapRoomAutoRegister`:新建房间 SO 自动注册到默认 Database不再需要策划手动拖入
- `MapDatabaseEditor`:一键 ValidateAll带 Ping 导航的房间列表
**遗留问题:**
- **N2 (P2)** `MapLayoutEditorWindow.DrawExitLines` 遍历每个房间的所有出口并各画一条线A→B 和 B→A 均被绘制,导致相同连线段出现双重叠画。虽然 R11-N10 修复了端点准确性,但未消除重复渲染
*建议:用 `HashSet<(string,string)>` 对每条连接对去重(规范化 key小 ID 在前),仅绘制一条*
- **N4 (P2)** `MapRoomAutoRegister` 未处理 `deletedAssets`:删除一个 `MapRoomDataSO` 后,其 null 引用仍留在 `MapDatabaseSO.AllRooms` 数组中,累积脏数据,需手动 ValidateAll 才能发现
*建议:在 `OnPostprocessAllAssets` 中遍历 `deletedAssets`,从所有 Database 清除匹配路径的 null 条目*
- `MapLayoutEditorWindow` 不支持在窗口内直接编辑出口数据ExitGridPos / Direction / TransitionType仍需切换到房间 Inspector在大型地图编辑时来回切换效率较低
### 5. 游戏功能完整性 (7.5/10) →
**已实现的核心功能(与行业标准对齐):**
- ✅ 三层可见度(未知 / 已探索 / 已标记)
- ✅ 玩家位置图标(房间内归一化插值定位)
- ✅ 自定义 Pin 标记(多类型 Sprite 可配)
- ✅ 区域名称渐显动画 + 本地化支持
- ✅ 存档/读档整合MapSaveData
- ✅ 当前房间高亮
- ✅ 面板打开时自动居中到当前房间
- ✅ 全屏地图滚动/缩放 + 出口连接线
- ✅ 角落 HUD 小地图(视角范围内增量渲染)
**缺口:**
- ❌ 小地图MinimapHUD不支持玩家控制的缩放仅有固定的 `_viewRadiusCells`
- ❌ 无探索进度百分比显示(全图 / 当前区域)
-`OnRoomMappedAnim` 虚方法预留了但方法体为空 `{}` ——新发现房间时无动画过渡效果(如淡入 reveal
- ❌ 未知房间仅为纯黑色,无雾效(纹理或渐变)处理,视觉层次略显单调
-`IPinService.CreatePin` 只接受 `RoomId + normalizedPos`,缺少基于世界坐标自动解析的便捷 API
- ❌ 无传送点/快速旅行 hook哪怕只是空接口预留
### 6. 代码质量 (8.5/10) →
**优点:**
- XML 文档完整,关键方法均有 `<summary>`
- 严格遵循 no-game-references 规则
- R11-N11 ValidateAll 特殊字符检查、R11-N9 `_worldOriginOffset` 均有 Tooltip 说明
- `[DefaultExecutionOrder(-700)]` 确保 MapManager 优先注册到 ServiceLocator
- `CompositeDisposable` 模式统一管理短期订阅,避免 OnDisable 时泄漏
**遗留问题:**
- **N3 (P2)** `MapPanel._pinSprites``MinimapHUD._pinSprites` 是各自独立的 `[SerializeField] PinSpriteEntry[]`,配置分散在两个 Prefab 中。新增 PinType 必须同时修改两处 Inspector 配置,容易漏改
*建议:提取 `MapPinConfigSO` ScriptableObject单一资产两个 UI 组件各持 `[SerializeField] MapPinConfigSO _pinConfig` 引用*
- **N10 (P3)** `MapPin.cs` 文件包含 `MapPinManager`注释注明是历史命名遗留文件名与主类名不匹配IDE 导航和资产搜索可能混淆
*建议:重命名文件为 `MapPinManager.cs` 或拆分为 `MapPin.cs`(数据类)+ `MapPinManager.cs`(管理类)*
### 7. 可扩展性 (8.0/10) ↑
**优点:**
- Interface-based 全面,可无缝替换 MapManager / MapPlayerTracker / MapPinManager 实现
- `OnRoomMappedAnim` `protected virtual` 支持 MapPanel 子类重写
- `MapServiceExtensions` 扩展方法模式,新功能无需修改接口定义
- `RegionNameEntry` 本地化支持LocKey 优先、DisplayName 回退
**遗留问题:**
- **N9 (P3)** 见数据设计章节,房间类型用 3 个 bool 字段,扩展新类型需改动 SO 类定义和 `ChooseIcon` 方法
- **N3 (P2)** PinSpriteEntry 配置未集中化,新增 PinType 涉及多处修改
---
## R12 Findings 汇总
| ID | 优先级 | 分类 | 描述 |
|----|--------|------|------|
| N1 | P2 | 性能 | `MapPanel` ClearExits / RebuildAll / OnDestroy 使用 `Destroy`,应补充格子/出口对象池 |
| N2 | P2 | 编辑器 | `DrawExitLines` 双向重复绘制需对连接对去重HashSet 规范化 key |
| N3 | P2 | 代码质量 | `PinSpriteEntry[]` 在 MapPanel 和 MinimapHUD 中各配一份,建议抽取 `MapPinConfigSO` |
| N4 | P2 | 编辑器 | `MapRoomAutoRegister` 未处理 `deletedAssets`,删除的房间 null 引用残留 Database |
| N5 | P2 | 数据设计 | `ExitGridPos == Vector2Int.zero` 哨兵与合法坐标 (0,0) 二义,建议 `HasCustomExitPos` bool |
| N6 | P3 | 性能 | `RegionNameDisplay.ResolveDisplayName` O(N) 线性查找,建议 Awake 预建 Dictionary |
| N7 | P3 | 架构 | `MapPanel.LateUpdate``_servicesReady` 标志,服务获取后仍每帧空跑 `SubscribeServices` |
| N8 | P3 | 架构 | `MapPanel` 对单房间探索变更双重刷新EventChannel + OnExplorationChanged 各触发一次) |
| N9 | P3 | 可扩展性 | `IsBossRoom` / `IsSavePoint` / `IsShop` 三 bool 字段,不及 `[Flags] RoomType` 枚举灵活 |
| N10 | P3 | 代码质量 | `MapPin.cs` 文件名与主类 `MapPinManager` 不匹配,建议重命名文件 |
**P1 阻断性缺陷0**
**P2 重要缺陷5**
**P3 次要缺陷5**
---
## R11 vs R12 对比
| 项目 | R11 评估时 | R12 评估时 |
|------|-----------|-----------|
| P1 缺陷数 | 4 | 0 ✅ |
| P2 缺陷数 | 5 | 5 |
| P3 缺陷数 | 3 | 5 |
| MinimapHUD 格子池 | ❌ 无 | ✅ `Stack<MapRoomCellUI>` |
| MapPanel 格子池 | ❌ 无 | ❌ 仍使用 Destroy |
| 输入系统 | ❌ 旧版 Input | ✅ InputSystem (`InputReaderSO`) |
| 出口线端点精度 | ❌ 目标中心 | ✅ ExitGridPos + 反向查找 |
| 编辑器缓存刷新 | ❌ 缺 OnProjectChange | ✅ `OnProjectChange()` 实现 |
| RoomId 验证 | 基础 | ✅ Trim + 特殊字符检查 |
---
## 改进建议优先级
### 立即执行P2
1. **[N1]** 为 `MapPanel` 补充格子与出口对象池,消除 RebuildAll GC 峰值
2. **[N2]** `MapLayoutEditorWindow.DrawExitLines``HashSet<(string,string)>` 去重,消除重复线段
3. **[N3]** 提取 `MapPinConfigSO`,统一 Pin 图标配置入口
4. **[N4]** `MapRoomAutoRegister` 处理 `deletedAssets`,自动清除 Database 中的 null 引用
5. **[N5]** `RoomExitData` 增加 `HasCustomExitPos` bool 字段,消除 zero 哨兵歧义
### 计划执行P3
6. **[N6]** `RegionNameDisplay.Awake` 预建 `Dictionary<string, RegionNameEntry>`
7. **[N7]** `MapPanel` 增加 `_servicesReady` 标志跳过已就绪后的 LateUpdate 查询
8. **[N8]** 审查 MapPanel 双重刷新路径,决策是否移除 `_onMapUpdated` EventChannel 依赖
9. **[N9]** 将 `IsBossRoom / IsSavePoint / IsShop` 重构为 `[Flags] RoomType` 枚举
10. **[N10]** 重命名 `MapPin.cs``MapPinManager.cs`(或拆分数据/管理两个文件)
---
## 综合评价
经过 R11 的 12 项修复,系统已消除所有 P1 阻断性缺陷,架构层面趋于稳定。当前版本在 InputSystem 集成、对象池、编辑器工具完整性、服务解耦等核心维度均达到商业标准。
剩余 R12 的 10 项 findings 均为 P2/P3 改善项不影响功能正确性主要涉及配置中心化N3/N9、编辑器视觉质量N2、运行时 GC 一致性N1、数据语义清晰度N5
**最终评分86.2/100B+**
> 达到可发布的商业 Metroidvania 小地图实现标准,剩余工作为进一步打磨的优化项,非阻断项。