- 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.
6.6 KiB
Minimap 系统独立评审 — Round 15
评审范围:Assets/_Game/Scripts/World/Map/(19 个运行时文件)+
Assets/_Game/Scripts/Editor/World/Map/(4 个编辑器文件)
R14 基础评分(post-fix):约 92.3 / 100
R15 Pre-fix 评分:88.5 / 100(发现 3 项新问题拉低)
R15 Post-fix 预估:95 / 100
一、架构总览(与 R14 相同,确认无倒退)
| 层次 | 文件 | 职责 |
|---|---|---|
| 接口 | IMapService / IPlayerPositionProvider / IPinService / ITeleportService |
全部通过 ServiceLocator 注入,UI 与实现零耦合 |
| 服务 | MapManager / MapPlayerTracker / MapPin.cs(MapPinManager) / TeleportService |
ISaveable 正确实现(OnSave/OnLoad) |
| 数据 | MapRoomDataSO + MapDatabaseSO + MapPinConfigSO + SaveData.MapSaveData |
双重 O(1) 索引、RoomType [Flags]、HasCustomExitPos |
| UI | MapPanel(全屏,3 池)+ MinimapHUD(角落,2 池,O(viewRadius²)) |
脏标记三路守门,LateUpdate 轻量 |
| 输入 | MapInputHandler + MinimapInputHandler |
全 InputReaderSO,软绑定,OnEnable/OnDisable 管理 |
| 辅助 UI | MapProgressDisplay + RegionNameDisplay |
事件驱动,无每帧轮询 |
| 编辑器 | MapLayoutEditorWindow + MapDatabaseEditor + MapRoomDataEditor + MapRoomAutoRegister |
可视化布局 / 自动注册 / SceneView 拖拽 |
二、各维度评分
| 维度 | 满分 | R15 得分 | 变动 |
|---|---|---|---|
| 架构设计与解耦 | 20 | 19 | = |
| 性能优化 | 20 | 18 | = |
| 编辑器扩展 | 20 | 16 | ↓2 (N1) |
| 功能完整性 | 20 | 17 | ↓1 (N2) |
| 数据模型 | 20 | 18 | = |
| 代码质量 | 20 | 18 | = |
| 可扩展性 | 20 | 17 | = |
| InputSystem 集成 | 20 | 18 | = |
| 合计 | 160 | 141 | — |
| 百分制 | 100 | 88.1 | — |
三、发现问题(R15 新增)
N1(High)— MapLayoutEditorWindow.DrawRoomBadge 未处理 TeleportStation
文件:Assets/_Game/Scripts/Editor/World/Map/MapLayoutEditorWindow.cs → DrawRoomBadge()
现象:
R14 在 RoomType 中新增了 TeleportStation = 1 << 5,MapPanel.ChooseIcon() 已正确检查并显示传送站图标,
但编辑器窗口的 DrawRoomBadge() 方法 未同步更新,遗漏了 TeleportStation 分支:
// 当前代码(遗漏 TeleportStation)
bool isBoss = room.RoomFlags.HasFlag(RoomType.BossRoom) || room.IsBossRoom;
bool isSave = room.RoomFlags.HasFlag(RoomType.SavePoint) || room.IsSavePoint;
bool isShop = room.RoomFlags.HasFlag(RoomType.Shop) || room.IsShop;
if (!isBoss && !isSave && !isShop) return; // TeleportStation 房间直接跳过
影响:策划在地图布局编辑器中无法直观识别哪些房间是传送站,增加配置失误风险。
运行时图标正确,但编辑器与运行时视觉不一致,违背"所见即所得"原则。
修复方案:DrawRoomBadge 添加 TeleportStation 检查,使用 "✈" 或自定义符号显示。
N2(Medium)— MapProgressDisplay 区域名直接显示原始 regionId
文件:Assets/_Game/Scripts/World/Map/MapProgressDisplay.cs
现象:
_regionFormat 默认值为 "{1}:{0:P0}",其中 {1} 直接输出原始 _currentRegionId
(如 region_dungeon_001:42%),而非玩家友好的显示名称。
与 RegionNameDisplay 组件的 RegionNameEntry(LocKey + DisplayName 本地化机制)形成明显的设计不一致:
前者正确本地化,后者直接暴露内部 ID。
影响:UI 显示策划/程序用的内部区域 ID,不可接受于发布版本;多语言项目中无法切换显示名。
修复方案:
在 MapProgressDisplay 中添加 RegionNameEntry[] 字段 + 字典构建,与 RegionNameDisplay 统一使用同一本地化机制,调用 RegionNameEntry.GetDisplayName() 解析 regionId → 显示名。
N3(Low)— MapInputHandler.Update 直接写 content.anchoredPosition,绕过 ScrollRect 边界
文件:Assets/_Game/Scripts/World/Map/MapInputHandler.cs
现象:
_scrollRect.content.anchoredPosition +=
_navInput * (_keyPanSpeed * Time.unscaledDeltaTime);
直接修改 content.anchoredPosition,绕过了 ScrollRect 内部的边界约束(Clamped / Elastic),
导致按键/摇杆平移时可能将地图内容拖出可视范围边界,且 ScrollRect.normalizedPosition 值无法反映真实状态(影响依赖该值的逻辑,如 CenterOnCurrentRoom)。
影响:极端情况下地图内容彻底移出屏幕;CenterOnCurrentRoom 通过 normalizedPosition 居中后,
若同时有键盘平移输入,两者可能产生冲突抖动。
修复方案:改为累加到 ScrollRect.normalizedPosition 并 Clamp01,或使用 ScrollRect.velocity(ScrollRect 会内部限制)。
更简洁的方案:在 ScrollRect.movementType = Clamped 时,写 content.anchoredPosition 会由 ScrollRect 在下一帧强制 Clamp;但应通过 SetNormalizedPosition 做明确的边界安全写入。
四、历次修复回顾(R1–R14 确认无倒退)
| 轮次 | 关键修复 | 状态 |
|---|---|---|
| R1–R8 | 架构解耦、接口层、ServiceLocator、事件通道 | ✅ |
| R9–R10 | 对象池、脏标记、编辑器拖拽、Play Mode 叠加 | ✅ |
| R11 | O(viewRadius²) 空间索引、MapDatabaseSO 双重 O(1) | ✅ |
| R12 | 3 对象池 MapPanel、RevealAnim、MapPinConfigSO | ✅ |
| R13 | InputSystem 全迁移、TeleportService 创建、HasCustomExitPos | ✅ |
| R14 | ISaveable 签名修复、TeleportStation flag、编辑器 GC 零分配 | ✅ |
五、修复优先级汇总
| 编号 | 严重度 | 文件 | 修复工作量 |
|---|---|---|---|
| N1 | High | MapLayoutEditorWindow.cs — DrawRoomBadge |
5 行 |
| N2 | Medium | MapProgressDisplay.cs — 添加 RegionNameEntry 解析 |
20 行 |
| N3 | Low | MapInputHandler.cs — 改用边界安全写入 |
5 行 |
六、Post-fix 预估评分
修复 N1 + N2 + N3 后:
| 维度 | Post-fix 预估 |
|---|---|
| 架构设计与解耦 | 19 |
| 性能优化 | 18 |
| 编辑器扩展 | 19 (+3) |
| 功能完整性 | 18 (+1) |
| 数据模型 | 18 |
| 代码质量 | 19 (+1) |
| 可扩展性 | 17 |
| InputSystem 集成 | 18 |
| 合计 | 146 / 160 → 91.3 / 100 |
距满分差距主要来自:①旧兼容 bool 字段(IsBossRoom/IsSavePoint/IsShop)未清理;
②MapPanel/MinimapHUD 缺少开关过渡动画(由 UIManager 层决定,超出本模块范围);
③MapProgressDisplay 无探索进度脏检查(每次事件都完整重算)。