- 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.
7.3 KiB
小地图系统独立评审 — Round 16
评审范围:
Assets/_Game/Scripts/World/Map/(19个运行时文件)+
Assets/_Game/Scripts/Editor/World/Map/(4个编辑器文件)
基线:R15 所有修复已验证到位(DrawRoomBadge TeleportStation、MapProgressDisplay 本地化、MapInputHandler normalizedPosition)
评审标准:2D 横版探索类游戏(银河恶魔城类型)小地图的架构、性能、编辑器、可扩展性综合标准
一、各维度评分(R16 当前状态)
| 维度 | 分值 | 说明 |
|---|---|---|
| 架构解耦 | 10/10 | 全接口驱动(IMapService / IPinService / IPlayerPositionProvider / ITeleportService),ServiceLocator 零硬依赖,事件频道单向通信 |
| 性能 | 9/10 | 3 对象池(MapPanel)+ 2 对象池(MinimapHUD),O(1) 空间索引,PinsVersion 脏检查,O(viewRadius²) 剔除,dirty 标志避免无效重建 |
| 编辑器扩展 | 8/10 | MapLayoutEditorWindow 功能完整、可视化拖拽;N1:DrawRoomBadge 优先级与运行时 ChooseIcon 不一致,存在误导 |
| 数据模型 | 9.5/10 | RoomType[Flags] 语义清晰,RoomExitData.HasCustomExitPos 消除哨兵值歧义,双重 O(1) 索引,MapRoomAutoRegister 自动化注册 |
| 存档系统 | 9.5/10 | 正确 ISaveable 签名(OnSave/OnLoad),防御性 List 拷贝,UnlockedTeleportRoomIds 完整,PinsVersion 存档后自增 |
| UI 完整性 | 8/10 | MapPanel 支持 4 种类型图标(存档/Boss/商店/传送);N2:MinimapHUD 始终传 null icon,小地图无房间类型图标 |
| 输入系统 | 9.5/10 | 完整 InputSystem 迁移,CycleMinimapZoomEvent / MapCenterEvent 软绑定,normalizedPosition 防越界 |
| 可扩展性 | 9/10 | PinType 扩展 MapPinConfigSO 即可,RoomType [Flags] 追加 bit,RegionNameEntry 通用机制 |
| 代码质量 | 8.5/10 | 注释详尽,防御性编程完善;N3:MapPinManager.CreatePin 未缓存 IMapService;N4:同类型字段名不一致 |
| 本地化 | 8.5/10 | RegionNameDisplay 和 MapProgressDisplay 均有本地化,机制共用;N4 字段名差异影响策划工作流 |
R16 综合评分(修复前):89.0 / 100
二、发现问题(4 项)
N1(中):DrawRoomBadge 优先级与运行时 ChooseIcon 不一致
文件:MapLayoutEditorWindow.cs 第 464 行
位置:DrawRoomBadge 函数
现象:
// 编辑器 DrawRoomBadge 当前顺序:
string badge = isBoss ? "★" : isSave ? "♦" : isTeleport ? "⇅" : "¥";
// Boss 第1 Save 第2 Teleport 第3 Shop 第4
// 运行时 MapPanel.ChooseIcon 顺序:
if (room.RoomFlags.HasFlag(RoomType.SavePoint) || room.IsSavePoint) return _iconSavePoint; // 第1
if (room.RoomFlags.HasFlag(RoomType.BossRoom) || room.IsBossRoom) return _iconBossRoom; // 第2
if (room.RoomFlags.HasFlag(RoomType.Shop) || room.IsShop) return _iconShop; // 第3
if (room.RoomFlags.HasFlag(RoomType.TeleportStation)) return _iconTeleport; // 第4
影响:当房间同时含 SavePoint + BossRoom flags 时,编辑器显示 ★(Boss),运行时显示 ♦(Save),严重误导策划检查地图标注结果。
修复:将 DrawRoomBadge 的优先级对齐运行时顺序:Save > Boss > Shop > Teleport。
N2(中):MinimapHUD 始终传 null 作为格子图标
文件:MinimapHUD.cs 第 333 行
位置:RefreshView > 格子创建分支
现象:
cell.Setup(room, _mapSvc.GetVisibility(room.RoomId), null); // 第三个参数始终 null
MapPanel.ChooseIcon 完整支持存档点/Boss/商店/传送站 4 种图标,但 MinimapHUD 完全不传图标。玩家在小地图上看不到任何特殊房间标识,与全屏地图视觉不对称。
修复:在 MinimapHUD 添加与 MapPanel 对齐的 4 个 Sprite 字段和 ChooseIcon 方法,Setup 调用传入实际图标。
N3(低):MapPinManager.CreatePin 每次调用 ServiceLocator
文件:MapPin.cs 第 80 行
现象:
var mapSvc = ServiceLocator.GetOrDefault<IMapService>(); // 每次 CreatePin 都查
所有其他服务(MapManager、MinimapHUD 等)均在 Awake/Start 缓存 ServiceLocator 引用。MapPinManager 是唯一例外。存档加载后如需重新创建多个 Pin,每次都触发一次 ServiceLocator 查找。
修复:添加 _mapSvc 私有字段,在 Start() 中缓存,CreatePin 直接使用缓存引用。
N4(低):MapProgressDisplay._regionNameEntries 与 RegionNameDisplay._regionNames 字段名不一致
文件:MapProgressDisplay.cs 第 29 行 vs RegionNameDisplay.cs
现象:两者均使用 RegionNameEntry[] 配置区域本地化,但 Inspector 字段名不同:
RegionNameDisplay:_regionNames(渲染区域名时查)MapProgressDisplay:_regionNameEntries(R15 新增)
策划为两个组件配置同一份数据时需记忆两个不同字段名,破坏工作流一致性。
修复:将 MapProgressDisplay._regionNameEntries 重命名为 _regionNames,加 [UnityEngine.Serialization.FormerlySerializedAs("_regionNameEntries")] 保持序列化兼容。
三、已确认正常的项目
| 项目 | 结论 |
|---|---|
| R15-N1 DrawRoomBadge TeleportStation | ✅ 已添加 isTeleport 分支 |
| R15-N2 MapProgressDisplay 本地化 | ✅ _regionDict O(1) 查找 + BuildRegionDict() |
| R15-N3 MapInputHandler normalizedPosition | ✅ Clamp01 防越界 |
| R14-N1 TeleportService ISaveable 签名 | ✅ OnSave/OnLoad 正确实现 |
| R14-N2 TeleportStation RoomType flag + MapPanel icon | ✅ 1<<5 bit 位,_iconTeleport |
| MapDatabaseSO 双重索引 | ✅ string→room + Vector2Int→roomId 均 O(1) |
| PinsVersion 脏检查 | ✅ MapPanel/MinimapHUD 均使用 |
| MapRoomAutoRegister AssetPostprocessor | ✅ 自动注册 + EditorPrefs 开关 |
| MapPanel._servicesReady 短路优化 | ✅ 三服务就绪后跳过 LateUpdate 查询 |
| DrawExitLines GC 缓存 | ✅ _drawnExitPairs + ExitLineColor 已为 class fields |
| MapInputHandler.OnScroll 以鼠标为缩放中心 | ✅ pivotBefore/pivotAfter 补偿正确 |
| MapPlayerTracker 单例保护 | ✅ Awake 检测重复实例 |
| RegionNameDisplay 本地化回退链 | ✅ LocKey → DisplayName → RegionId 三级回退 |
四、修复后预估评分
| 修复 | 增量 |
|---|---|
| N1 修复:DrawRoomBadge 优先级对齐 | +1.0 |
| N2 修复:MinimapHUD 支持类型图标 | +1.5 |
| N3 修复:MapPinManager 缓存 IMapService | +0.5 |
| N4 修复:字段名统一为 _regionNames | +0.5 |
R16 修复后预估评分:92.5 / 100
五、架构总结
经过 16 轮迭代,小地图系统已达到成熟商业品质:
- 零具体类依赖:所有模块间通信经由接口 + ServiceLocator + 事件频道
- 编辑器支持完整:可视化布局编辑、自动注册、实时验证、场景覆盖
- 性能基础扎实:5 个对象池、O(1) 空间查询、多层 dirty flag 机制
- 存档健壮:防御性拷贝、版本化 PinsVersion、探索状态完整持久化
- 输入系统现代化:全 InputSystem 软绑定,键盘/手柄/鼠标三路径均正确
主要剩余改进空间:UI 入场/出场过渡动画(属 UIManager 层职责,在本模块范围外)。