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

9.1 KiB
Raw Permalink Blame History

小地图系统独立评审 Round 22

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


R21 修复确认

编号 内容 状态
R21-N1 MinimapHUD._servicesReady + LateUpdate 重试(对齐 MapPanel 确认L66, L197-203
R21-N1 MapPlayerTracker [DefaultExecutionOrder(-600)] 确认L17
R21-N2 MapPanel 集合字段补全 readonly 确认L58-63
R21-N3 MinimapHUD.UnsubscribeServices 重置 _servicesReady 确认L158

各维度评分

1. 架构设计Architecture 19.0 / 20

亮点

  • ServiceLocator + 4 接口IMapService / IPinService / IPlayerPositionProvider / ITeleportService零耦合
  • 事件驱动C# Action无轮询OnDatabaseChanged / OnExplorationChanged / OnRoomMapped 语义分明
  • ISaveable 三处防御性拷贝对称MapManager / MapPinManager / TeleportService
  • MapRoomCellUI 双视图复用,无重复 Prefab
  • ChooseDisplayIcon 唯一入口MapRoomDataSOMapPanel / MinimapHUD 无漂移
  • MapServiceExtensions 无状态扩展方法,消费方零重复查询逻辑

新发现问题 N1中等RegionNameEntry 字典解析逻辑在两个组件重复

RegionNameDisplayMapProgressDisplay 各自独立实现了完全相同的模式:

// RegionNameDisplay
private Dictionary<string, RegionNameEntry> _regionDict;
private void BuildRegionDict() { ... }
private string ResolveDisplayName(string regionId) { ... }

// MapProgressDisplay
private Dictionary<string, RegionNameEntry> _regionDict;
private void BuildRegionDict() { ... }
private string ResolveRegionDisplayName(string regionId) { ... }

两者代码几乎逐行相同(包含 LocKey 优先、DisplayName 次之、RegionId 回退三段逻辑),仅方法名不同。 修复建议:在 MapServiceExtensions.cs 中补充静态扩展方法 BuildRegionDict / ResolveDisplayName 两个组件调用同一实现,消除 DRY 违反。

扣分1.0


2. 性能Performance 19.5 / 20

亮点

  • MapPanel 全部 readonly 集合池 × 6Cell / Pin / ExitMinimapHUD × 4
  • _servicesReady 短路MapPanel R12-N7MinimapHUD R21-N1消除每帧 ServiceLocator 查询
  • O(viewRadius²) 空间索引,大地图下 MinimapHUD.RefreshView 比 O(AllRooms) 显著降低开销
  • 复用缓冲区:_toRemove / _roomsInViewBuffer / _newlyAddedBuffer(预分配容量)
  • PinsVersion 脏检查 + 玩家位置脏检查消除无效写入
  • _regionCache 懒加载MapManager_regionDict 字典化RegionNameDisplay / MapProgressDisplay

说明(信息级)MapProgressDisplay.Refresh() 区域进度遍历为 O(rooms_in_region) 但仅在 OnExplorationChanged 或区域切换时触发(非每帧),当前规模无性能风险。

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


3. 代码质量Code Quality 19.0 / 20

亮点

  • 全部集合字段已补齐 readonlyMapPanel R21-N2 修复)
  • CurrentZoom 属性R19-N1消除双份状态
  • RunRevealAnim 自清理协程R20-N1
  • HasCustomExitPos 语义布尔替代哨兵
  • [Obsolete] + [HideInInspector] 废弃字段注解完整
  • DrawLine try/finally 保证 GUI.matrix 恢复R11-N12
  • MapPin.cs 文件头注释标明"文件名历史遗留,请搜索类名 MapPinManager"

新发现问题 N2轻微:编辑器 DrawRoomBadge 注释引用已过时

// MapLayoutEditorWindow.cs L488
// 优先级与运行时 MapPanel.ChooseIcon 对齐Save > Boss > Shop > Teleport

R20-N2 已将运行时图标选取逻辑迁移至 MapRoomDataSO.ChooseDisplayIcon MapPanel.ChooseIcon 已变为单行委托。注释应更新为:

// 优先级与运行时 MapRoomDataSO.ChooseDisplayIcon 对齐Save > Boss > Shop > Teleport

扣分1.0N1 DRY 违反产生的代码质量问题)


4. 编辑器扩展Editor Tools 14.5 / 15

亮点

  • MapLayoutEditorWindow:缩放/平移/拖拽/搜索/区域着色/验证/Undo/热改完整
  • _cachedZoomForStyle 脏检查 + _noResultStyle 首次初始化缓存
  • DrawExitLines 字段级去重 _drawnExitPairsOnGUI 零分配
  • SetDatabase 公共 API避免 MapDatabaseEditor 反射访问私有字段
  • MapRoomAutoRegister AssetPostprocessor 自动注册工作流完整

扣分0.5DrawRoomBadge 注释引用过时,对策划人员阅读代码时产生误导)


5. 功能完整性Feature Completeness 15.0 / 15

亮点(所有功能均已实现且正确)

  • 三级可见性Unknown / Explored / Mapped+ 雾效覆盖层
  • 图标优先级唯一入口Override > SavePoint > Boss > Shop > Teleport
  • Pin 系统(持久化、类型化、视野内渲染)
  • 出口连接线 + Fallback 位置R13-N1 HasCustomExitPos
  • 传送系统TeleportService解锁 / 验证 / 请求 / 完成回调)
  • 区域检测 + 区域名本地化显示RegionNameDisplay + MapProgressDisplay
  • 存档/读档ISaveable 三处,防御性拷贝对称)
  • 房间发现动画RevealAnim 自清理R20-N1
  • 全屏地图 + 角落 HUD 双视图小地图视野档位切换CycleZoom

扣分0


6. 输入系统Input System 9.5 / 10

亮点

  • 全部使用 InputSystemInputReaderSO
  • MapInputHandlerNavigate / MapCenter / OnScroll 完整
  • MinimapInputHandlerCycleMinimapZoom 路由
  • OnEnable/OnDisable 对称订阅/取消

信息级MapInputHandler._zoomOnScroll 中作为本地累加器,与 _panel.CurrentZoom 读取路径不同但结果一致OnScroll 写 → CurrentZoom 读,无环),正确配置下无实际风险。

扣分0.5(轻微职责重叠,不影响正确性)


综合评分

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

问题清单与修复建议

N1 — RegionNameEntry 字典解析逻辑重复(中优先级)

根因RegionNameDisplayMapProgressDisplay 独立实现了相同的 BuildRegionDict + Resolve 模式。

修复方案:在 MapServiceExtensions.cs 追加静态扩展/工具方法:

/// <summary>
/// 将 RegionNameEntry 数组构建为 O(1) 查询字典。
/// RegionNameDisplay / MapProgressDisplay 共享此实现,消除重复。
/// </summary>
public static Dictionary<string, RegionNameEntry> BuildRegionDict(RegionNameEntry[] entries)
{
    var dict = new Dictionary<string, RegionNameEntry>();
    if (entries == null) return dict;
    foreach (var e in entries)
        if (!string.IsNullOrEmpty(e.RegionId))
            dict[e.RegionId] = e;
    return dict;
}

/// <summary>从字典解析 regionId 的玩家可读显示名;字典为 null 时直接回退到 regionId。</summary>
public static string ResolveRegionDisplayName(
    Dictionary<string, RegionNameEntry> dict, string regionId)
{
    if (dict != null && dict.TryGetValue(regionId, out var e))
        return e.GetDisplayName();
    return regionId;
}

两个组件改为:

private void BuildRegionDict()
    => _regionDict = MapServiceExtensions.BuildRegionDict(_regionNames);

private string ResolveDisplayName(string regionId)
    => MapServiceExtensions.ResolveRegionDisplayName(_regionDict, regionId);

N2 — DrawRoomBadge 注释引用过时(低优先级)

修复MapLayoutEditorWindow.cs L488 注释更新:

// 优先级与运行时 MapRoomDataSO.ChooseDisplayIcon 对齐Save > Boss > Shop > Teleport

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

MapPinManager.Awake 注册 IPinService,若晚于 UI 的 SubscribeServices 调用, _pinService 将在首帧为 null_servicesReady 重试机制兜底)。 两 UI 的 _servicesReady 短路已覆盖此场景,但显式标注执行顺序更具防御性:

[DefaultExecutionOrder(-500)]  // 晚于 MapPlayerTracker(-600),早于默认 0
public class MapPinManager : MonoBehaviour, ISaveable, IPinService

评分历史

轮次 评分 关键改动
R17 93.0
R18 93.8 MinimapHUD 废弃 _onMapUpdated 订阅
R19 93.8 CurrentZoom 属性_revealCoroutines 防泄漏
R20 94.2 RunRevealAnim 自清理ChooseDisplayIcon 集中
R21 95.0 MinimapHUD _servicesReadyMapPlayerTracker 执行顺序readonly 补全
R22 96.5 R21 修复确认;识别 N1RegionNameEntry DRYN2注释过时N3MapPinManager 执行顺序)