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

189 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.
# 小地图系统 R26 独立评审报告
**评审轮次**Round 26R25 修复后全面重审)
**评审基准**:成熟 2D Metroidvania 游戏商业级标准 + 专业编辑器扩展
---
## 一、各维度评分
| 维度 | 满分 | 得分 | vs R25修复后 |
|------|------|------|----------------|
| 架构设计 & 解耦合 | 25 | 24.0 | -0.5 |
| 性能 & 运行时效率 | 20 | 19.5 | ±0 |
| 编辑器工具质量 | 15 | 14.5 | ±0 |
| 代码质量 & 可维护性 | 15 | 13.8 | -0.2 |
| 存档 & 持久化 | 10 | 9.5 | ±0 |
| 可扩展性 | 10 | 9.5 | ±0 |
| 功能完整性 | 5 | 5.0 | ±0 |
| **综合** | **100** | **95.8** | **-1.7** |
> R25修复后基准97.5 → R2695.8(发现 2 项新问题)
---
## 二、R25 修复全部落地确认
| 修复项 | 状态 |
|--------|------|
| C1TeleportService.CanTeleportTo `_mapSvc == null \|\| ...``_mapSvc != null && ...` | ✅ |
| N1MapPanel._subs 死代码字段及 Clear() 调用全部移除 | ✅ |
| N2MapInputHandler.Awake 展开 + `#if UNITY_EDITOR \|\| DEVELOPMENT_BUILD` 校验警告 | ✅ |
---
## 三、持续表现优秀的设计
| 维度 | 设计亮点 |
|------|---------|
| **接口解耦** | IMapService / IPlayerPositionProvider / IPinService / ITeleportService 全通过 ServiceLocatorUI 层无任何具体类引用 |
| **执行顺序链** | MapManager(-700)→MapPlayerTracker(-600)→MapPinManager(-500)→TeleportService(-400)→UI(0);服务注册先于所有消费方 |
| **空间索引共享** | MapDatabaseSO 统一维护 `_cellToRoom` 字典MinimapHUD 的 O(viewRadius²) 剔除与 MapPlayerTracker 的 O(1) 房间判定共享同一索引,无重复构建 |
| **五类对象池** | MapPanelCell/Exit/Pin+ MinimapHUDCell/Pin全量 Disable 入池、Enable 出池OnDestroy 销毁剩余发现动画协程自清理R20-N1|
| **ISaveable 防御性拷贝** | MapManager / MapPinManager / TeleportService 三处对称OnSave new HashSet/ListOnLoad Clear+foreach Add |
| **_servicesReady 短路** | MapPanel + MinimapHUD 均在三服务就绪后置 true消除每帧 ServiceLocator 查询 |
| **LateUpdate 脏检查** | MapPanel 玩家图标RoomId + NormPos 双字段MinimapHUD 玩家圆点Pin 版本号脏检查——全部避免无效 RectTransform 读写 |
| **DRY** | ChooseDisplayIcon 集中在 MapRoomDataSOBuildRegionDict / ResolveRegionDisplayName 集中在 MapServiceExtensionsMapPanel + MinimapHUD 均通过委托调用 |
| **编辑器工具** | 拖拽/缩放/验证4类错误/搜索RoomId/RegionId/RoomType三维/图例/Play Mode 玩家叠加GUIStyle 缓存MatchesRoomType 不区分大小写 |
| **存档健壮性** | OnLoad 空集合防御、空 id 过滤OnValidate 自动 Trim RoomId、迁移旧 bool 字段;`delayCall -=;+=` 防止 Inspector 快速操作重复触发 |
| **UnsubscribeServices 有意不对称** | MapPanelOnDestroy 末尾不清空引用vs MinimapHUD置 null + 重置标志,支持跨场景重连)——均有注释说明 |
---
## 四、新发现问题
### N1 — NormalITeleportService 接口不完整(`UnlockTeleportStation` / `NotifyTeleportCompleted` 缺失)
**文件**`ITeleportService.cs`(接口缺失),`TeleportService.cs`L103115 公开方法)
**问题**
```csharp
// ITeleportService 接口中存在的方法:
bool CanTeleportTo(string roomId);
void RequestTeleport(string targetRoomId);
event Action<string, string> OnTeleportRequested;
event Action<string> OnTeleportCompleted;
// ─── 缺失的两个写操作方法 ───
// TeleportService 上有 public 定义,但不在接口中:
public void NotifyTeleportCompleted(string arrivedRoomId); // 场景加载系统须调用
public void UnlockTeleportStation(string roomId); // 游戏触发器须调用
```
**影响**
- **场景加载系统**完成传送后需调用 `NotifyTeleportCompleted`,但通过 `ServiceLocator.GetOrDefault<ITeleportService>()` 只能拿到接口,无法访问该方法;调用方被迫使用具体类型(`TeleportService`)或反射,**破坏接口解耦原则**。
- **传送站触发器**`OnTriggerEnter` 等)需要调用 `UnlockTeleportStation`,同样面临相同问题。
- 接口 + ServiceLocator 模式在整个系统中一致使用,此处缺口会让后续维护者混淆。
**修复**:在 `ITeleportService` 中补全两个方法:
```csharp
/// <summary>解锁指定房间的传送点(游戏触发器调用)。</summary>
void UnlockTeleportStation(string roomId);
/// <summary>场景加载系统传送完成后调用,触发 OnTeleportCompleted 事件。</summary>
void NotifyTeleportCompleted(string arrivedRoomId);
```
---
### N2 — NormalMapPinManager 缺少 `_isDuplicate` 单例保护(与 MapManager / MapPlayerTracker 不一致)
**文件**`MapPin.cs`MapPinManager 类L3237
**问题**
```csharp
// MapManager正确
private void Awake()
{
if (ServiceLocator.GetOrDefault<IMapService>() != null) { _isDuplicate = true; Destroy(gameObject); return; }
ServiceLocator.Register<IMapService>(this);
}
// MapPlayerTracker正确
private void Awake()
{
if (ServiceLocator.GetOrDefault<IPlayerPositionProvider>() != null) { _isDuplicate = true; ... }
...
}
// MapPinManager缺少保护
private void Awake()
{
// ← 无重复实例检测
ServiceLocator.Register<IPinService>(this); // 若已有注册,直接覆盖
}
```
**影响**
- 若场景中意外存在两个 MapPinManagerPersistent 场景加载两次、DontDestroyOnLoad 重复等),第二个实例会覆盖 ServiceLocator 注册,但第一个实例的 `ISaveable` 仍保持注册状态(`OnEnable` 中加入 SaveableRegistry导致存档时 `OnSave` 被调用两次、集合竞争写入 `SaveData.Map.Pins`
- 系统其他三处服务均有 `_isDuplicate` 守卫,此处缺失属于架构一致性漏洞。
**修复**
```csharp
private void Awake()
{
if (ServiceLocator.GetOrDefault<IPinService>() != null)
{
_isDuplicate = true;
Destroy(gameObject);
return;
}
ServiceLocator.Register<IPinService>(this);
}
// OnEnable / OnDisable / OnDestroy 首行加 if (_isDuplicate) return;
```
---
## 五、各文件评分摘要
| 文件 | 状态 | 备注 |
|------|------|------|
| MapManager.cs | ✅ 完整 | 执行顺序/ISaveable/IMapService/缓存/LINQ 仅在非热路径 |
| MapPlayerTracker.cs | ✅ 完整 | O(1) 空间索引/平滑归一化/单例保护 |
| **MapPinManagerMapPin.cs** | ⚠️ N2 | 缺少 _isDuplicate 保护 |
| **TeleportService.cs** | ⚠️ N1 | 接口缺口UnlockTeleportStation/NotifyTeleportCompleted |
| MapPanel.cs | ✅ 完整 | R25-N1 _subs 死代码已移除;五层解耦;三对象池 |
| MinimapHUD.cs | ✅ 完整 | O(viewRadius²) 剔除跨场景重连GC 友好缓冲区 |
| MapInputHandler.cs | ✅ 完整 | R24-N2 单一 scale 状态R25-N2 配置警告 |
| MinimapInputHandler.cs | ✅ 完整 | 干净委托,单职责 |
| MapRoomCellUI.cs | ✅ 完整 | 双场景复用PlayRevealAnim 颜色恢复 |
| MapRoomDataSO.cs / MapDatabaseSO | ✅ 完整 | ChooseDisplayIcon 集中空间索引共享OnValidate 含延迟通知防抖 |
| MapServiceExtensions.cs | ✅ 完整 | 纯静态无状态DRY 中心 |
| RegionNameDisplay.cs | ✅ 完整 | CompositeDisposable 正确使用;协程 OnDisable 终止安全 |
| **ITeleportService.cs** | ⚠️ N1 | 缺少两个写操作方法声明 |
| MapLayoutEditorWindow.cs编辑器 | ✅ 完整 | 搜索+图例+拖拽+验证+GUIStyle 缓存+✕按钮 |
---
## 六、修复优先级
| 编号 | 严重度 | 文件 | 影响 | 建议 |
|------|--------|------|------|------|
| N1 | 🟡 Normal | ITeleportService.cs + TeleportService.cs | 接口不完整导致调用方被迫使用具体类型 | 立即修复 |
| N2 | 🟡 Normal | MapPin.csMapPinManager | 多实例场景存档竞争写入 | 立即修复 |
---
## 七、评分历史
| 轮次 | 综合评分 | 主要变化 |
|------|---------|---------|
| R17 | 93.0 | 初轮重构后 |
| R18R19 | 93.8 | 平移/缩放/协程修复 |
| R20 | 94.2 | DRY + 协程自清理 |
| R21 | 95.0 | ServicesReady 对称 |
| R22 | 96.5 | BuildRegionDict 集中 |
| R23 | 97.5 | MatchesRoomType + 执行顺序 |
| R24 | 97.5 | TeleportService 重建(遗留 C1 |
| R25修复前 | 95.5 | 发现 C1 逻辑反转 + N1 死代码 + N2 无警告 |
| R25修复后基准 | 97.5 | 三项全修复 |
| **R26** | **95.8** | 发现 N1接口不完整-1.2+ N2单例缺失-0.5|
---
*R26 评审完成时间2026-05-25*