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

Minimap System — Round 18 Independent Review

评审范围

全部 23 个源文件4 接口 + 15 运行时 + 4 编辑器),在 R17 全部修复已落地的基础上进行全面重新审查。


R17 修复确认

编号 描述 验证状态
R17-N1 删除 MapLayoutEditorWindow._cachedErrorRoomIds 死代码字段 已确认,字段已不存在
R17-N2 搜索活跃时非匹配房间 alpha 0.28 → 0.08 已确认,第 335 行
R17-N3 搜索无结果时居中显示提示文本 已确认,第 363373 行

R18 全方面评分(修复前)

维度 权重 分数 说明
架构解耦 20% 95 四接口全 ServiceLocator事件单向流无循环依赖服务订阅 Awake 长期持有不随 OnEnable/Disable 失效
功能完整性 20% 92 三级可见性、Pin、传送、本地化区域名、地图碎片解锁动画、存档一致全部覆盖
性能 15% 91 三池cell/pin/exit+ O(viewRadius²) 剔除 + PinsVersion 脏检查 + _servicesReady 短路N1 键盘平移未乘缩放N3 MinimapHUD 双重刷新
编辑器工具 15% 93 布局编辑器:拖拽/搜索/图例/Play Mode 叠加/Undo-Redo/AssetPostprocessor 自动注册R17 UX 修复有效N2 每帧重建 noResultStyle
可扩展性 10% 95 RoomType[Flags] 可任意叠加新类型SO 驱动接口易替换MapPinConfigSO 集中 Pin 配置
代码质量 10% 93 命名规范、注释充实、防御拷贝三处对称N2 GUIStyle 每 OnGUI 帧重建
玩家体验设计 10% 88 键盘平移范围未乘 _zoom,缩放后平移速度感知偏差

综合修复前92.4 / 100


R18 新发现问题

N1正确性MapInputHandler 键盘平移范围未乘缩放系数

文件Assets/_Game/Scripts/World/Map/MapInputHandler.cs 第 7687 行

现状

Vector2 contentSize  = content.rect.size;
Vector2 viewportSize = viewport.rect.size;
float   rangeX = contentSize.x - viewportSize.x;
float   rangeY = contentSize.y - viewportSize.y;

RectTransform.rect.size 是本地空间(未缩放)的尺寸。当 _zoomTarget.localScale = (_zoom, _zoom, 1) 改变后,内容在屏幕上的视觉尺寸为 contentSize × _zoomScrollRect 的实际可滚动范围也随之放大。

当前代码中 rangeX = contentSize.x - viewportSize.x 不含缩放因子,导致:

  • 放大时(_zoom > 1):每帧移动距离 delta.x / rangeX 被高估,平移速度感知快于预期;
  • 缩小时(_zoom < 1):平移速度感知慢于预期;
  • 同样问题影响 MapPanel.CenterOnCurrentRoom 中的 rangeX / rangeY 计算。

修复

// MapInputHandler.Update
float rangeX = contentSize.x * _zoom - viewportSize.x;
float rangeY = contentSize.y * _zoom - viewportSize.y;

// MapPanel.CenterOnCurrentRoom — 同步修复 rangeX/rangeY
float rangeX = contentSize.x * /* zoom */ - viewSize.x;  // 需从 MapInputHandler 传入或独立持有

注意MapPanel.CenterOnCurrentRoom 中无法直接读取 MapInputHandler._zoom;最简方案是从 _roomContainer.localScale.x 读取当前缩放值。


N2编辑器性能noResultStyle 每次 OnGUI 重新分配

文件Assets/_Game/Scripts/Editor/World/Map/MapLayoutEditorWindow.cs 第 365371 行

现状

var noResultStyle = new GUIStyle(EditorStyles.boldLabel)
{
    alignment = TextAnchor.MiddleCenter,
    normal    = { textColor = new Color(1f, 0.8f, 0.2f, 0.8f) },
    fontSize  = 13,
};

此段仅在"搜索有内容 && 无匹配"时执行,但每次 OnGUI(编辑器 60 fps 或更高频率)均分配一个新 GUIStyle 对象。与已有的 _roomLabelStyle_badgeBossStyle_badgeNormalStyle 的缓存模式不一致。

修复:添加 _noResultStyle 字段,在 EnsureLabelStyles() 中一并初始化(fontSize = 13 固定,无需随 _zoom 变化)。


N3架构一致性MinimapHUD 保留 _onMapUpdated 订阅导致双重刷新

文件Assets/_Game/Scripts/World/Map/MinimapHUD.cs 第 90 行 + 第 205209 行

现状

// OnEnable:
_onMapUpdated?.Subscribe(OnMapUpdated).AddTo(_subs);

// OnMapUpdated:
private void OnMapUpdated(string roomId)
{
    if (_cells.TryGetValue(roomId, out var cell))
        cell.SetVisibility(_mapSvc.GetVisibility(roomId));
}

MapPanel 已在 R12-N8 移除 _onMapUpdated 订阅,改由 OnExplorationChanged 统一处理。但 MinimapHUD 未跟进:

每次房间被探索或标记时,MapManager 先后触发:

  1. _onMapUpdated?.Raise(roomId)MinimapHUD.OnMapUpdated(roomId) — 更新单个格子
  2. OnExplorationChanged?.Invoke()MinimapHUD.OnExplorationChanged() — 刷新全部活跃格子

步骤 1 的工作完全被步骤 2 覆盖造成重复写入。对于小视野49 格)影响可忽略,但在视野半径较大时每次探索会多做一次无效的单格更新。

修复:从 MinimapHUD 移除 _onMapUpdated SerializeField 及其订阅,保留 [HideInInspector, SerializeField] 字段并标注废弃说明(与 MapPanel 的处理方式对齐,保留 Prefab 序列化兼容性),删除 OnMapUpdated 私有方法。


架构深度审查

接口层4 接口)

接口 实现 注册方式 状态
IMapService MapManager ServiceLocator.Register<T> in Awake 完整
IPinService MapPinManager ServiceLocator in Awake 完整
IPlayerPositionProvider MapPlayerTracker ServiceLocator in Awake 完整
ITeleportService TeleportService ServiceLocator in Awake 完整

存档一致性3 处 ISaveable

实现类 防御拷贝 覆盖加载 广播更新
MapManager.OnSave/OnLoad new HashSet<>(_x) new HashSet<> 后赋值 OnExplorationChanged?.Invoke()
MapPinManager.OnSave/OnLoad new List<>(_pins) new List<> 后赋值 PinsVersion++
TeleportService.OnSave/OnLoad new HashSet<>(_unlockedRoomIds) Clear + foreach Add (通过传送服务事件)

对象池完整性

容纳类型 所在组件 入池时机
_cellPool MapRoomCellUI MapPanel RebuildAll
_pinPool Image (Pin) MapPanel ClearPins
_exitPool Image (Exit) MapPanel ClearExits
_cellPool MapRoomCellUI MinimapHUD RefreshView 裁剪过期格子
_pinPool Image (Pin) MinimapHUD ClearPins

性能关键路径

路径 复杂度 机制
MinimapHUD.RefreshView 新格子查询 O(viewRadius²) MapDatabaseSO.GetRoomIdAtCell 共享空间索引
MapPanel.LateUpdate 服务查询 O(1) 短路 _servicesReady bool 门控
MapPanel.LateUpdate Pin 渲染 O(1) 检查 PinsVersion 脏检查
MapManager.GetRoomsByRegion O(1) _regionCache 懒加载字典
MapDatabaseSO.GetRoom O(1) _index 字符串→SO 哈希索引
MapDatabaseSO.GetRoomIdAtCell O(1) _cellToRoom 格子坐标→ID 空间索引
MinimapHUD.UpdatePlayerDot O(1) roomId + NormPos 双字段脏检查
MapLayoutEditorWindow.EnsureLabelStyles O(1) _cachedZoomForStyle 脏检查

编辑器工具覆盖面

工具 能力
MapLayoutEditorWindow 可视化布局预览;滚轮缩放;中键/Alt 平移房间拖拽编辑Undo区域配色验证 + 错误高亮搜索高亮R17 UX 改善图例Play Mode 玩家点叠加
MapDatabaseEditor Inspector 内嵌"在布局编辑器中打开"按钮
MapRoomDataEditor SceneGUI 双角控制点可视化 GridPosition/GridSize
MapRoomAutoRegister AssetPostprocessor 自动注册新 SO 到默认 Database删除 null 清理;可禁用

R18 修复预期评分

维度 权重 当前 修复后 变化
架构解耦 20% 95 95
功能完整性 20% 92 92
性能 15% 91 93 +2N1+N3
编辑器工具 15% 93 94 +1N2
可扩展性 10% 95 95
代码质量 10% 93 95 +2N2+N3 架构一致)
玩家体验设计 10% 88 92 +4N1 修复后平移手感正确)

综合修复前92.4 / 100 → 修复后93.8 / 100


总结

经过 18 轮迭代,小地图系统整体架构已达到生产级 2D 探索类游戏标准:

  • 接口完整四接口零具体类依赖ServiceLocator 完全解耦
  • 存档对称:三处 ISaveable 均实现防御拷贝,读档后广播正确事件
  • 性能到位:五池 + O(viewRadius²) + 多级脏检查 + _servicesReady 短路
  • 编辑器成熟拖拽、搜索、Undo、Play Mode 叠加、自动注册一体化

R18 新发现 3 项问题均为低/中优先级不影响功能正确性N1 影响手感N2/N3 为轻微性能与架构一致性问题)。