Files
zeling_v2/Docs/Review/Minimap_Review_Round21_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

233 lines
8.5 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.
# 小地图系统独立评审 Round 21
**评审时间**R21基于 R20 全部修复已落地的代码基线)
**评审范围**`Assets/_Game/Scripts/World/Map/` 全部 19 个运行时文件 + 4 个编辑器扩展文件
**评分基准**:专业 2D Metroidvania 编辑器扩展标准(架构解耦 / 高性能 / 可扩展 / 开发者友好)
---
## R20 修复确认
| 编号 | 内容 | 状态 |
|------|------|------|
| R20-N1 | `RunRevealAnim` 包装协程,完成后 `_revealCoroutines.Remove(roomId)` | ✅ 确认L214-218 |
| R20-N2 | `ChooseDisplayIcon` 集中到 `MapRoomDataSO`MapPanel/MinimapHUD 改单行委托 | ✅ 确认L61-69 / L478-480 / L367-368 |
---
## 各维度评分
### 1. 架构设计Architecture 18.5 / 20
**亮点**
- ServiceLocator + 4 接口层IMapService / IPinService / IPlayerPositionProvider / ITeleportService完全解耦
- 事件驱动C# Action无轮询
- ISaveable 三处防御性拷贝对称实现
- MapRoomCellUI 在 MapPanel / MinimapHUD 共享,零重复 Prefab
- `ChooseDisplayIcon` R20-N2 后唯一入口,无漂移风险
**新发现问题 N1中等严重**`MinimapHUD` 缺少 LateUpdate 服务重试机制
`MapPanel.LateUpdate` 对未就绪的服务执行重试:
```csharp
// MapPanel.cs L169-170
if (!_servicesReady)
SubscribeServices();
```
`MinimapHUD` 仅在 `Awake``OnEnable` 中调用 `SubscribeServices()`**无 LateUpdate 重试**。
`MapPlayerTracker`IPlayerPositionProvider`[DefaultExecutionOrder]`,初始化顺序不确定:
-`MinimapHUD.Awake` 先于 `MapPlayerTracker.Awake` 执行 → `_playerProvider` 永久为 null
- 后果:玩家圆点不渲染,`OnRoomChanged` 永不触发HUD 完全静止
**扣分1.5**
---
### 2. 性能Performance 19.5 / 20
**亮点**
- MapPanel 3 对象池Cell / Pin / ExitMinimapHUD 2 对象池Cell / Pin
- O(viewRadius²) 空间索引查询(共享 `MapDatabaseSO._cellToRoom`
- `_servicesReady` 短路MapPanel消除每帧 ServiceLocator 查询
- `_revealCoroutines` 自清理R20-N1
- 复用缓冲区:`_toRemove` / `_roomsInViewBuffer` / `_newlyAddedBuffer`
- PinsVersion 脏检查 + 玩家位置脏检查
- `_regionCache` 懒加载,避免 LINQ 全扫
**说明**(信息级,不扣分):`MapPanel.BuildGrid` 末尾调用 `LayoutRebuilder.ForceRebuildLayoutImmediate`
`_scrollRect.content` 含 ContentSizeFitter此调用是必要的确保 `CenterOnCurrentRoom` 读到正确 content 尺寸);无 LayoutGroup 时代价极低。设计合理。
**扣分0.5**MinimapHUD 无 _servicesReady 短路,每次 OnEnable 均执行三次 ServiceLocator 查询)
---
### 3. 代码质量Code Quality 18.5 / 20
**亮点**
- `CurrentZoom` 属性R19-N1消除双份状态
- `RunRevealAnim` 自清理协程R20-N1
- `ChooseDisplayIcon` 单一职责集中R20-N2
- OnValidate RoomFlags 迁移兼容
- `HasCustomExitPos` 语义布尔替代哨兵值
- `[Obsolete]` + `[HideInInspector]` 废弃字段注解完整
**新发现问题 N2轻微**`MapPanel` 集合字段缺少 `readonly` 修饰
`MinimapHUD` 同类字段已标 `readonly`,两者不一致:
```csharp
// MinimapHUD.cs已正确标注
private readonly Dictionary<string, MapRoomCellUI> _cells = new();
private readonly List<Image> _pinImages = new();
private readonly Stack<Image> _pinPool = new();
private readonly Stack<MapRoomCellUI> _cellPool = new();
// MapPanel.cs缺少 readonly可被意外重新赋值
private Dictionary<string, MapRoomCellUI> _cells = new();
private List<Image> _pinImages = new();
private Stack<Image> _pinPool = new();
private Stack<MapRoomCellUI> _cellPool = new();
private Stack<Image> _exitPool = new();
private List<Image> _exitImages= new();
```
`_revealCoroutines` 已正确标 `readonly`,其余集合字段漏标。
**扣分1.0**N2 readonly 不一致)+ **0.5**MapInputHandler `_zoom``OnScroll` 仍作为局部累加器,与 `_zoomTarget.localScale.x` 功能重叠,配置错误时存在漂移风险)
---
### 4. 编辑器扩展Editor Tools 14.5 / 15
**亮点**
- `MapLayoutEditorWindow`:缩放/平移/拖拽/搜索/区域着色/验证/Undo/热改
- `_cachedZoomForStyle` 脏检查Style 不在每帧重建
- `_noResultStyle` 首次初始化缓存R18-N2
- `MapDatabaseEditor``MapRoomDataEditor``MapRoomAutoRegister` 覆盖完整工作流
- `DrawExitLines` 去重缓存(`_drawnExitPairs`
**扣分0.5**(信息级:`MapLayoutEditorWindow` 无单元测试覆盖)
---
### 5. 功能完整性Feature Completeness 14.5 / 15
**亮点**
- 三级可见性Unknown / Explored / Mapped完整实现
- 类型图标优先级Override > SavePoint > Boss > Shop > Teleport
- Pin 系统(持久化、类型化、可视半径内渲染)
- 出口连接线 + Fallback 位置R13-N1
- 区域检测与 RegionChanged 事件
- 存档/读档ISaveable
- 房间发现动画RevealAnim 自清理)
- 全屏地图 + 角落 HUD 双视图
**N1 影响**:若 MinimapHUD 初始化顺序不利,玩家圆点和 HUD 响应将缺失,属功能可靠性问题。**扣分0.5**
---
### 6. 输入系统Input System 9.5 / 10
**亮点**
- 全部使用 InputSystemInputReaderSO
- `MapInputHandler`Navigate / MapCenter / OnScroll
- `MinimapInputHandler`CycleMinimapZoom
- OnEnable/OnDisable 对称订阅/取消
**扣分0.5**(信息级:`MapInputHandler._zoom``_panel.CurrentZoom` 职责轻微重叠)
---
## 综合评分
| 维度 | 满分 | 得分 |
|------|------|------|
| 架构设计 | 20 | 18.5 |
| 性能 | 20 | 19.5 |
| 代码质量 | 20 | 18.5 |
| 编辑器扩展 | 15 | 14.5 |
| 功能完整性 | 15 | 14.5 |
| 输入系统 | 10 | 9.5 |
| **合计** | **100** | **95.0** |
> R21 较 R2094.2)略有提升,主要因 R20 修复全部落地确认;
> N1服务重试缺失是本轮最高优先级问题。
---
## 问题清单与修复建议
### N1 — MinimapHUD 缺少服务重试(高优先级)
**根因**`MapPlayerTracker``[DefaultExecutionOrder]`,可能晚于 `MinimapHUD` 注册服务。
**修复方案 A推荐防御性最强**:在 `MinimapHUD.LateUpdate` 中补充重试。
```csharp
// MinimapHUD.cs
private bool _servicesReady;
private void LateUpdate()
{
if (!_servicesReady)
SubscribeServices();
UpdatePlayerDot();
RenderPinsIfDirty();
}
private void SubscribeServices()
{
// 原有逻辑不变,末尾加:
if (_playerProvider != null && _mapSvc != null && _pinService != null)
_servicesReady = true;
}
```
**修复方案 B互补**:给 `MapPlayerTracker` 加执行顺序,确保早于无顺序 MonoBehaviour 注册。
```csharp
[DefaultExecutionOrder(-600)] // 晚于 MapManager(-700),早于默认 0
public class MapPlayerTracker : MonoBehaviour, IPlayerPositionProvider
```
**建议两个方案同时实施**B 保证常规路径A 防御异常路径。
---
### N2 — MapPanel 集合字段缺少 `readonly`(低优先级)
**修复**:在 `MapPanel.cs` 的集合字段声明处补充 `readonly`
```csharp
private readonly Dictionary<string, MapRoomCellUI> _cells = new();
private readonly List<Image> _pinImages = new();
private readonly Stack<Image> _pinPool = new();
private readonly Stack<MapRoomCellUI> _cellPool = new();
private readonly Stack<Image> _exitPool = new();
private readonly List<Image> _exitImages= new();
```
---
### N3 — MinimapHUD.OnDisable 未重置 `_servicesReady`(伴随 N1 修复引入)
实施 N1 修复后,若 `_servicesReady` 不在 `UnsubscribeServices` / `OnDestroy` 时重置,销毁后重建场景的实例将跳过重订阅。
```csharp
private void UnsubscribeServices()
{
_servicesReady = false; // 补充
// 其余原有逻辑不变
}
```
---
## 评分历史
| 轮次 | 评分 | 关键改动 |
|------|------|----------|
| R14 | 92.3 | — |
| R15 | 91.3 | — |
| R16 | 92.5 | — |
| R17 | 93.0 | — |
| R18 | 93.8 | MinimapHUD 废弃 _onMapUpdated 订阅 |
| R19 | 93.8 | CurrentZoom 属性_revealCoroutines 防泄漏 |
| R20 | 94.2 | RunRevealAnim 自清理ChooseDisplayIcon 集中 |
| **R21** | **95.0** | R20 修复确认;识别 N1服务重试缺失N2readonlyN3执行顺序 |