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.
This commit is contained in:
2026-05-25 23:15:12 +08:00
parent e2bc324905
commit f74d7f1877
53 changed files with 6825 additions and 270 deletions

View File

@@ -0,0 +1,203 @@
# 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 小地图实现标准,剩余工作为进一步打磨的优化项,非阻断项。