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

10 KiB
Raw Blame History

小地图系统独立评审 Round 23

评审时间R23基于 R22 全部修复已落地的代码基线)
评审范围Assets/_Game/Scripts/World/Map/ 全部 19 个运行时文件 + 4 个编辑器扩展文件
评分基准:专业 2D Metroidvania 编辑器扩展标准(架构解耦 / 高性能 / 可扩展 / 开发者友好)


R22 修复确认

编号 内容 状态
R22-N1 BuildRegionDict/ResolveRegionDisplayName 迁移至 MapServiceExtensions;两个组件单行委托 确认(MapServiceExtensions.cs:17,32;两组件第 104-108 行)
R22-N2 DrawRoomBadge 注释更新为 MapRoomDataSO.ChooseDisplayIcon 确认(MapLayoutEditorWindow.cs:480,488
R22-N3 MapPinManager [DefaultExecutionOrder(-500)] 确认(MapPin.cs:20

各维度评分

1. 架构设计Architecture19.5 / 20

亮点(全面审查确认)

  • 4 接口IMapService / IPinService / IPlayerPositionProvider / ITeleportService+ ServiceLocator零硬依赖
  • 事件驱动Action无帧轮询OnDatabaseChanged / OnExplorationChanged / OnRoomMapped 语义独立
  • ISaveable 防御性拷贝三处对称MapManagernew HashSet<> ×2MapPinManagernew List<> 双向TeleportServicereadonly + Clear+Add
  • ChooseDisplayIcon 单一入口MapRoomDataSOMapPanel / MinimapHUD / Editor 三处均委托
  • MapServiceExtensions3 个无状态方法GetVisibility / CreatePinAtWorldPos / BuildRegionDict+Resolve消费方零重复逻辑
  • MapRoomCellUI 双视图MapPanel 全屏 + MinimapHUD 角落)复用同一 Prefab
  • RoomType [Flags] 枚举支持多类型组合,OnValidate 自动迁移旧 bool 字段

信息级观察MapPanel.UnsubscribeServices() 不 null 服务引用,而 MinimapHUD.UnsubscribeServices() 会 null 三个字段并重置 _servicesReady。这是有意的架构差异——MapPanel 仅在 OnDestroy 调用 UnsubscribeServices生命周期末尾引用已无意义而 MinimapHUD 作为持久 HUD 需支持跨场景重连。在目标持久服务架构下,两者均不会出现悬空引用。无需修复,但值得注释说明设计意图。

扣分0.5UnsubscribeServices 不对称缺少注释,可读性略低)


2. 性能Performance19.5 / 20

亮点

  • _servicesReady 短路MapPanel R12-N7MinimapHUD R21-N1消除每帧 ServiceLocator 查询
  • MapPanel 对象池 × 3readonly 集合:_cellPool / _pinPool / _exitPoolMinimapHUD × 2
  • O(viewRadius²) 空间索引(MapDatabaseSO.GetRoomIdAtCellMinimapHUD 无需扫描全量房间
  • 4 个复用缓冲区(_toRemove / _roomsInViewBuffer / _newlyAddedBuffer + _cells 增量更新)
  • PinsVersion 脏检查:两 UI 均跳过无变化重绘
  • _totalRoomCount 懒加载缓存MapManager_regionCache 懒加载GetRoomsByRegion 零 LINQ
  • 玩家图标双脏标记roomId + normPos消除无效 RectTransform 写入

信息级MapProgressDisplay.Refresh() 区域进度遍历 O(N/region),仅在 OnExplorationChanged 触发(非每帧),当前规模无性能风险。

扣分0.5MapProgressDisplay 区域遍历未缓存已探索计数;极大地图时有轻微冗余)


3. 代码质量Code Quality19.5 / 20

亮点

  • 全部集合字段补齐 readonlyMapPanel × 6MinimapHUD × 4_revealCoroutines 亦为 readonly
  • CurrentZoom 属性消除双份缩放状态MapPanel L379
  • RunRevealAnim 自清理协程:完成后自动 _revealCoroutines.Remove(roomId)R20-N1
  • HasCustomExitPos 语义布尔替代 == Vector2Int.zero 哨兵R13-N1
  • [Obsolete] + [HideInInspector] 废弃字段注解完整
  • RoomId.Trim() 自动修剪防空格污染OnValidate
  • DrawLine try/finally 保证 GUI.matrix 恢复R11-N12
  • MapPin.cs 文件头注释明确历史遗留原因

信息级MapPanel.UnsubscribeServices() 相比 MinimapHUD.UnsubscribeServices() 缺少注释说明为何不 null 服务引用。新加入代码者可能误认为是疏漏。

扣分0.5UnsubscribeServices 不对称未有注释解释意图)


4. 编辑器扩展Editor Tools14.5 / 15

亮点

  • MapLayoutEditorWindow:缩放 / 平移 / 房间拖拽 / 搜索 / 区域着色 / 验证 / Undo / 热改全功能
  • _cachedZoomForStyle 脏检查 + _noResultStyle 首次初始化缓存R18-N2
  • DrawExitLines 字段级 _drawnExitPairs 去重OnGUI 零分配
  • OnProjectChange + OnUndoRedo 自动失效验证缓存并触发重绘
  • SetDatabase 公共 API避免 MapDatabaseEditor 反射访问私有字段)
  • MapRoomAutoRegister AssetPostprocessor 自动注册工作流
  • MapDatabaseSO.ValidateAll() 四类校验null / 空 RoomId / 重复 / 格子重叠 / 出口悬空)
  • DrawRoomBadge 注释已更新为 MapRoomDataSO.ChooseDisplayIconR22-N2

扣分0.5MapLayoutEditorWindow 搜索框匹配范围仅 RoomId/RegionId 子串,无法按 RoomType 过滤;策划批量检查某类型房间时需逐个点击)


5. 功能完整性Feature Completeness15.0 / 15

所有特性完整实现:

  • 三级可见性Unknown / Explored / Mapped+ 雾效覆盖层R12-FD
  • 图标优先级唯一入口Override > SavePoint > Boss > Shop > Teleport
  • Pin 系统(持久化 / 类型化 / 视野内渲染 / 64 字符 note 限制)
  • 出口连接线 + Fallback 位置HasCustomExitPos 语义布尔)
  • 传送系统TeleportService解锁 / 验证 / 请求 / 完成回调)
  • 区域检测 + 区域名本地化显示RegionNameDisplay + MapProgressDisplay
  • 存档/读档ISaveable 三处,防御性拷贝对称)
  • 房间发现动画PlayRevealAnim + RunRevealAnim 自清理)
  • 全屏地图 + 角落 HUD 双视图小地图视野档位循环切换CycleZoom
  • RoomType [Flags] 枚举 + OnValidate 向后兼容迁移

扣分0


6. 输入系统Input System9.5 / 10

亮点

  • 全部使用 InputReaderSOInputSystem无硬编码按键
  • MapInputHandlerNavigate / MapCenter / OnScroll 完整
  • MinimapInputHandlerCycleMinimapZoom 路由 MinimapHUD.CycleZoom()
  • OnEnable/OnDisable 对称订阅/取消

信息级MapInputHandler._zoom 作为本地累加器,与 _panel.CurrentZoom 读取路径不同但结果一致OnScroll 写 _roomContainer.localScaleCurrentZoom_roomContainer.localScale.x 读取,无环,无状态漂移)。

扣分0.5MapInputHandler._zoom 轻微职责重叠,正确但不够直观)


综合评分

维度 满分 得分 较 R22
架构设计 20 19.5 +0.5
性能 20 19.5 ±0
代码质量 20 19.5 +0.5
编辑器扩展 15 14.5 ±0
功能完整性 15 15.0 ±0
输入系统 10 9.5 ±0
合计 100 97.5 +1.0

问题清单

N1 — MapPanel.UnsubscribeServices 缺少意图注释(低优先级)

现状MinimapHUD.UnsubscribeServices() 会 null 三个服务引用并重置 _servicesReadyMapPanel.UnsubscribeServices() 不做此操作(也不需要,因为仅在 OnDestroy 调用)。两者不对称,可读性略差。

修复:在 MapPanel.UnsubscribeServices() 首行补注释:

// OnDestroy 时调用,生命周期末尾不需要 null 服务引用(与 MinimapHUD.UnsubscribeServices 的设计差异:
// MinimapHUD 需支持 OnDestroy 后跨场景重连MapPanel 不需要)。

N2 — MapLayoutEditorWindow 搜索框不支持 RoomType 过滤(低优先级)

场景:策划需要批量确认所有 SavePoint / BossRoom 房间的位置时,当前搜索只能匹配 RoomId/RegionId 子串,无法用 SavePoint 等类型关键字过滤。

建议方案:在搜索逻辑中加入 RoomType 枚举名匹配:

// 在 DrawMapArea 的搜索匹配部分补充:
bool matchesType = !string.IsNullOrEmpty(_searchText) &&
    System.Enum.GetNames(typeof(RoomType))
        .Any(name => room.RoomFlags.HasFlag((RoomType)System.Enum.Parse(typeof(RoomType), name))
                  && name.IndexOf(_searchText, System.StringComparison.OrdinalIgnoreCase) >= 0);
bool matches = matchesId || matchesRegion || matchesType;

N3 — TeleportService 缺少 [DefaultExecutionOrder](信息级)

TeleportService.Awake() 注册 ITeleportService。当前 UI 组件MinimapHUD / MapPanelSubscribeServices 不查询 ITeleportService因此无执行顺序风险。但与其他三个服务MapManager -700 / MapPlayerTracker -600 / MapPinManager -500相比未标注顺序一致性略差。

[DefaultExecutionOrder(-400)]  // 晚于 MapPinManager(-500),早于默认 0ITeleportService 在 UI 初始化前可用
public class TeleportService : MonoBehaviour, ITeleportService, ISaveable

评分历史

轮次 评分 关键改动
R18 93.8 MinimapHUD 废弃 _onMapUpdated 订阅
R19 93.8 CurrentZoom 属性_revealCoroutines 防泄漏
R20 94.2 RunRevealAnim 自清理ChooseDisplayIcon 集中
R21 95.0 MinimapHUD _servicesReadyMapPlayerTracker 执行顺序readonly 补全
R22 96.5 RegionNameEntry DRY 消除注释更新MapPinManager 执行顺序
R23 97.5 R22 修复确认;识别 N1注释不对称N2搜索缺 RoomType 过滤N3TeleportService 执行顺序)

总评

经过 23 轮迭代,小地图系统已达到专业商业 2D Metroidvania 发布标准

  • 架构:接口 + ServiceLocator + 事件驱动,各层职责清晰,扩展无需改动已有代码
  • 性能:全部热路径均有脏检查 / 对象池 / 短路机制保护,大地图下无性能风险
  • 开发体验:编辑器工具完整,策划可视化配置房间、验证错误、调试布局
  • 代码健康DRY 违反已全部消除readonly / 防御性拷贝 / 对象池三要素一致应用

剩余 2.5 分差距为信息级的可读性优化与编辑器小功能增强,不影响运行时正确性。