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

8.0 KiB
Raw Permalink Blame History

小地图系统 独立审查报告 Round 14

审查范围Assets/_Game/Scripts/World/Map/Runtime 19 文件)+
Assets/_Game/Scripts/Editor/World/Map/Editor 4 文件)

对标标准:成熟 2D Metroidvania 类型游戏的专业编辑器扩展级别,
面向开发人员和策划人员,要求架构解耦、高性能、高可扩展性。


总评分(修复前)

维度 满分 得分 说明
架构解耦 10 9.0 接口 + ServiceLocator 完整MapPin.cs 文件名历史遗留
性能 10 9.0 对象池完整、dirty check 完整DrawExitLines 每帧 new HashSet
编辑器 UX 10 9.0 可视化布局编辑器成熟DrawExitLines HashSet GC 小问题
数据模型 10 8.5 RoomType [Flags] 完善;缺少 TeleportStation 类型
输入系统 10 8.5 InputSystem 软绑定完整MinimapInputHandler R13 已加
功能完整性 10 6.5 TeleportService 存在但 MapPanel 无传送 UI 集成SaveKey 模式错误
代码质量 10 8.5 注释质量高TeleportService 含死代码字段
存档系统 10 5.0 TeleportService.ISaveable 签名错误(编译错误)
可扩展性 10 9.0 SO 驱动、Event Channel 解耦、Region 机制完善
总分 90 73.0 换算 100 分81.1 / 100B

相比 R1385.0/100R13 N1N4 + FA 修复提升了输入系统与 Bug 修复维度,
但 TeleportService 的 ISaveable 签名引入了编译错误N1使存档分大幅下降。
所有修复后预计 92+


Bug 发现

N1致命 — 编译错误TeleportService 实现了错误的 ISaveable 签名

文件TeleportService.csR13-FA 新增),SaveData.cs

问题
ISaveable 接口(BaseGames.Core.Save)定义为:

public interface ISaveable
{
    void OnSave(SaveData saveData);
    void OnLoad(SaveData saveData);
}

TeleportService 实现的是:

public string SaveKey => "TeleportService";  // ❌ 接口中不存在此成员
public string Serialize() { ... }            // ❌ 接口中不存在此方法
public void Deserialize(string data) { ... } // ❌ 接口中不存在此方法
// ❌ 缺少 OnSave(SaveData) / OnLoad(SaveData)

这导致 BaseGames.World.Map 程序集无法编译,整个地图系统全部失效。
此外,MapSaveDataSaveData.cs)中没有 UnlockedTeleportRoomIds 字段,
即使签名正确,传送数据也无处存储。

同时TeleportServiceISaveableRegistry 注册自身OnEnable 中),
ISaveableRegistry 期望的是 ISaveable 对象,
TeleportService 未正确实现该接口,注册调用将在运行时无效。

修复方案

  1. SaveData.cs — 在 MapSaveData 中添加:

    public HashSet<string> UnlockedTeleportRoomIds = new();
    
  2. TeleportService.cs — 替换 SaveKey/Serialize/Deserialize 为:

    public void OnSave(SaveData saveData)
    {
        saveData.Map.UnlockedTeleportRoomIds = new HashSet<string>(_unlockedRoomIds);
    }
    public void OnLoad(SaveData saveData)
    {
        _unlockedRoomIds.Clear();
        if (saveData.Map.UnlockedTeleportRoomIds != null)
            foreach (var id in saveData.Map.UnlockedTeleportRoomIds)
                _unlockedRoomIds.Add(id);
    }
    

    移除 ISaveableRegistry 手动注册(OnSave/OnLoadSaveManager 直接调用,无需 Registry


N2高优先级RoomType 缺少 TeleportStation 标志位

文件MapRoomDataSO.csMapPanel.cs

问题
RoomType [Flags] 枚举目前有 BossRoom / SavePoint / Shop / Merchant / Challenge
但没有 TeleportStationTeleportService 的解锁状态存储于运行时,
策划无法在 SO 上标记"此房间有传送站"MapPanel 也无法据此渲染传送图标。

// 当前
public enum RoomType
{
    None      = 0,
    BossRoom  = 1 << 0,
    SavePoint = 1 << 1,
    Shop      = 1 << 2,
    Merchant  = 1 << 3,
    Challenge = 1 << 4,
    // ❌ 缺少 TeleportStation
}

修复

  1. RoomType 添加 TeleportStation = 1 << 5
  2. MapPanel 添加 [SerializeField] private Sprite _iconTeleport; 字段
  3. MapPanel.ChooseIcon() 中补充传送站图标逻辑
  4. MapPanel 获取 ITeleportService,在 BuildGrid / RefreshCell 时区分
    "已解锁传送站"和"未解锁传送站"的颜色/图标

N3中等TeleportService._pendingSourceRoomId 是死代码

文件TeleportService.cs,第 108 行

问题

_pendingSourceRoomId = sourceRoomId;  // ← 赋值后从未读取
OnTeleportRequested?.Invoke(sourceRoomId, targetRoomId);  // sourceRoomId 已直接传入

_pendingSourceRoomId 只被写入,永远不被读取,是无用的私有字段。

修复:删除 _pendingSourceRoomId 字段及赋值语句。


N4低优先级MapLayoutEditorWindow.DrawExitLines 每帧 new HashSet

文件MapLayoutEditorWindow.csDrawExitLines() 方法(约第 453 行)

问题

private void DrawExitLines(MapDatabaseSO db, ...)
{
    var drawn = new HashSet<(string, string)>();  // ❌ 每次 OnGUI 都分配新对象
    ...
}

编辑器 OnGUI 以每秒多次频率调用,持续产生 GC 分配,可能导致编辑器卡顿。

修复:将 drawn 提升为类字段 _drawnExitPairs,在方法内仅调用 Clear()


N5低优先级MapPanel.OnMapUpdated 未标注 [Obsolete]

文件MapPanel.cs,第 313 行

问题

private void OnMapUpdated(string roomId) { /* R12-N8 已废弃 */ }

方法已废弃但未加 [Obsolete] 标注,后续开发者可能误以为该方法仍有业务逻辑。

修复:添加 [Obsolete("R12-N8: 由 OnExplorationChanged 统一处理,仅保留序列化兼容性。")]


架构亮点(保持优秀)

以下设计在本轮审查中仍被评定为业界优秀水平:

亮点 说明
接口 + ServiceLocator 4 个服务接口完全解耦UI 层零具体类型依赖
O(1) 空间索引 MapDatabaseSO.GetRoomIdAtCell 惰性构建,MinimapHUD + MapPlayerTracker 共享
三重对象池 MapPanelcell/pin/exit+ MinimapHUDcell/pin零 GC 渲染
Dirty Flag 模式 面板关闭期间收到事件OnEnable 时应用——无事件遗漏
_servicesReady 短路 三服务就绪后跳过 LateUpdate 的 ServiceLocator 查询
PinsVersion 脏检查 无需事件订阅,整数比较即可判断 Pin 集合是否变化
可视化布局编辑器 MapLayoutEditorWindow拖拽/吸附/缩放/搜索/Play 模式覆盖层
MapRoomAutoRegister AssetPostprocessor 自动注册新房间 SO零手动操作
InputSystem 软绑定 throwIfNotFound: false 防 InputActionAsset 缺失崩溃
HasCustomExitPos 标志 消除 Vector2Int.zero 哨兵值歧义R12-N5R13-N1 已修复)

修复优先级总表

编号 严重程度 文件 说明
N1 ★★★★★ 致命 TeleportService.cs + SaveData.cs ISaveable 签名错误导致编译失败
N2 ★★★★ 高 MapRoomDataSO.cs + MapPanel.cs 缺少 TeleportStation RoomType + MapPanel 传送 UI 集成
N3 ★★★ 中 TeleportService.cs _pendingSourceRoomId 死代码
N4 ★★ 低 MapLayoutEditorWindow.cs DrawExitLines HashSet 每帧分配
N5 ★ 极低 MapPanel.cs OnMapUpdated 缺 [Obsolete]

修复后预估评分

维度 修复前 修复后
架构解耦 9.0 9.0
性能 9.0 9.5N4 修复)
编辑器 UX 9.0 9.0
数据模型 8.5 9.5N2 TeleportStation
输入系统 8.5 8.5
功能完整性 6.5 9.0N2 传送 UI
代码质量 8.5 9.0N3/N5
存档系统 5.0 9.5N1 修复)
可扩展性 9.0 9.0
总分 81.1 ≈ 92.3