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

205 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# 小地图系统 R25 独立评审报告
**评审轮次**Round 25R24 修复后全面重审)
**评审基准**:成熟 2D Metroidvania 游戏的商业级标准;编辑器工具须对开发者/策划可用友好
---
## 一、各维度评分
| 维度 | 满分 | 得分 | 变化 |
|------|------|------|------|
| 架构设计 & 解耦合 | 25 | 24.5 | ±0 |
| 性能 & 运行时效率 | 20 | 19.5 | ±0 |
| 编辑器工具质量 | 15 | 14.5 | ±0 |
| 代码质量 & 可维护性 | 15 | 13.5 | -0.5 |
| 存档 & 持久化 | 10 | 9.0 | -0.5 |
| 可扩展性 | 10 | 9.5 | ±0 |
| 功能完整性 | 5 | 5.0 | ±0 |
| **综合** | **100** | **95.5** | **-2.0** |
> R24 得分97.5 → R25 得分95.5(发现 1 Critical + 2 Normal 问题)
---
## 二、确认正常的设计R24 修复全部落地)
| 项 | 状态 |
|----|------|
| TeleportService 完整重建135 行) | ✅ |
| RequestTeleport 源 RoomId 改为 IPlayerPositionProvider.CurrentRoomId | ✅ |
| MapInputHandler 删除 _zoom 双重状态OnScroll 直接读写 _zoomTarget.localScale.x | ✅ |
| MapLayoutEditorWindow 搜索框 ✕ 清除按钮 | ✅ |
| 执行顺序链MapManager(-700)→MapPlayerTracker(-600)→MapPinManager(-500)→TeleportService(-400)→UI(0) | ✅ |
| ISaveable 防御性拷贝三处对称 | ✅ |
| _servicesReady 短路MapPanel & MinimapHUD 对称) | ✅ |
| MapRoomDataSO.ChooseDisplayIcon DRY 消除 | ✅ |
| MapServiceExtensions 集中 BuildRegionDict / ResolveRegionDisplayName | ✅ |
| 三对象池MapPanelCell/Exit/PinMinimapHUDCell/Pin | ✅ |
| 发现动画协程自清理R20-N1 RunRevealAnim | ✅ |
| MinimapHUD O(viewRadius²) 空间索引裁剪 | ✅ |
| UnsubscribeServices 有意不对称注释说明 | ✅ |
---
## 三、新发现问题
### C1 — CriticalTeleportService.CanTeleportTo 逻辑反转Fail-Open 安全漏洞)
**文件**`Assets/_Game/Scripts/World/Map/TeleportService.cs`
**行号**L8182
**问题**
```csharp
_mapSvc ??= ServiceLocator.GetOrDefault<IMapService>();
return _mapSvc == null || _mapSvc.IsExplored(roomId); // ← BUG
```
`_mapSvc` 查询失败(服务未注册、场景切换中等)时,返回 `true`(允许传送)。
而注释明确写道:**"需要玩家已探索过目标房间(仅已知位置才允许传送)"**。
逻辑与意图完全相反:
- 实际行为:`_mapSvc == null`**无条件放行**Fail-Open
- 预期行为:`_mapSvc == null`**拒绝传送**Fail-Safe
**影响**:玩家可在 MapService 不可用时(存档切换、热重载等边缘时机)跳过探索校验,传送到从未到达过的房间,破坏探索核心机制。
**修复**
```csharp
return _mapSvc != null && _mapSvc.IsExplored(roomId);
```
---
### N1 — NormalMapPanel._subs 声明但永远为空(死代码)
**文件**`Assets/_Game/Scripts/World/Map/MapPanel.cs`
**行号**L76声明、L109Clear
**问题**
```csharp
private readonly CompositeDisposable _subs = new(); // 永远不会有内容
// ...
private void OnDisable()
{
_subs.Clear(); // ← 空操作
// ...
}
```
MapPanel 的所有事件订阅均通过直接 `+=` / `-=` 方式管理(在 `SubscribeServices` / `UnsubscribeServices` 中),没有任何订阅通过 `.AddTo(_subs)` 加入。`_subs.Clear()` 是一个完全的空操作。
**影响**:轻微;不影响运行时行为,但
1. 误导后续维护者(以为订阅已通过 CompositeDisposable 管理)
2. 在 OnDisable 中清理了并不存在的订阅,逻辑意图不清晰
**修复选项 A推荐**:删除 `_subs` 字段和 `_subs.Clear()` 调用,保持现有 `+=` 管理方式即可(已有 `UnsubscribeServices` 妥善处理)。
---
### N2 — NormalMapInputHandler 缺少 _zoomTarget 配置校验
**文件**`Assets/_Game/Scripts/World/Map/MapInputHandler.cs`
**行号**L21 注释、L97 & L382MapPanel.CurrentZoom
**问题**
- `MapInputHandler._zoomTarget` 注释写"通常为 _roomContainer格子根节点"
- `MapPanel.CurrentZoom` 明确读取 `_roomContainer.localScale.x`
- `MapInputHandler.OnScroll` 写入 `_zoomTarget.localScale`
- 若在 Inspector 中将 `_zoomTarget` 配置为非 `_roomContainer` 的节点,两者的 scale 将静默分裂:`CurrentZoom` 读到的是旧值,`OnScroll` 写入的是新值,缩放操作功能性损坏但无任何报错
**影响**:仅在配置错误时触发,但属于"配置错误无提示"的隐患,在 Prefab 调试时难以定位。
**修复**:在 Awake 中添加运行时校验警告:
```csharp
private void Awake()
{
_panel = GetComponent<MapPanel>();
#if UNITY_EDITOR || DEVELOPMENT_BUILD
if (_zoomTarget != null && _panel != null)
{
// MapPanel.CurrentZoom 读取 _roomContainer要求 _zoomTarget 与其为同一节点
Debug.LogWarning("[MapInputHandler] _zoomTarget 应配置为 MapPanel 的 _roomContainer格子根节点" +
"否则 CurrentZoom 与缩放操作将读写不同节点导致状态分裂。", this);
}
#endif
}
```
> 更优做法:提供 `public void SetZoomTarget(RectTransform t)` 由 MapPanel.OnEnable 注入,彻底消除配置依赖。
---
## 四、各文件详细状态
### MapPanel.cs
- 架构五层解耦Interface → ServiceLocator → C# Events → UI → Object Pool
- 性能:三对象池 + PinsVersion 脏检查 + _servicesReady 短路 ✅
- **死代码**`_subs` 字段N1
- 其余对象池三种Cell/Exit/Pin均正确入池、出池、OnDestroy 销毁 ✅
### MinimapHUD.cs
- O(viewRadius²) 空间索引裁剪 ✅
- _servicesReady 短路 + 跨场景重连null 服务引用 + 重置标志)✅
- GC 友好:复用 `_toRemove``_roomsInViewBuffer``_newlyAddedBuffer`
- 无新问题 ✅
### MapInputHandler.cs
- R24-N2 修复落地:无独立 `_zoom` 字段OnScroll 直接读写 `_zoomTarget.localScale.x`
- **配置隐患**:缺少 `_zoomTarget` 校验N2
### TeleportService.cs
- R24 完整重建架构正确ISaveable / ITeleportService / 单例保护 ✅
- **C1 逻辑反转**`CanTeleportTo``_mapSvc == null` 时 Fail-Open ❌
### MapManager.cs
- 执行顺序 (-700) / ISaveable / IMapService ✅
- `GetRoomsByRegion` 懒加载缓存 ✅
- `NotifyDatabaseChanged` 同步清空区域缓存 ✅
### MapPinManager.cs (MapPin.cs)
- 执行顺序 (-500) / ISaveable / IPinService ✅
- PinsVersion 脏版本号 ✅
### MapServiceExtensions.cs
- 无状态扩展方法集 ✅
- GetVisibility / CreatePinAtWorldPos / BuildRegionDict / ResolveRegionDisplayName ✅
### MapLayoutEditorWindow.cs编辑器
- 拖拽/缩放/验证/搜索/图例/Play Mode 玩家点 ✅
- ✕ 清除按钮R24-N3
- MatchesRoomType RoomType 枚举搜索R23-N2
- GUIStyle 缓存(避免 60fps × 100 房间重分配)✅
- Undo.undoRedoPerformed 注册 ✅
---
## 五、修复优先级
| 编号 | 严重度 | 文件 | 影响 | 是否立即修复 |
|------|--------|------|------|-------------|
| C1 | 🔴 Critical | TeleportService.cs | Fail-Open 逻辑反转,破坏探索机制 | 是 |
| N1 | 🟡 Normal | MapPanel.cs | 死代码误导维护 | 推荐 |
| N2 | 🟡 Normal | MapInputHandler.cs | 配置错误无提示 | 推荐 |
---
## 六、评分历史
| 轮次 | 综合评分 | 主要变化 |
|------|---------|---------|
| R17 | 93.0 | 初轮大规模重构后 |
| R18 | 93.8 | 平移/缩放 + 协程修复 |
| R19 | 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-1.5+ N1-0.25+ N2-0.25|
> R25 评分低于 R24因 R24 重建 TeleportService 时引入了 C1 逻辑反转错误fail-open vs fail-safe该问题在 R24 评审中被遗漏。
---
*R25 评审完成时间2025*