# 小地图系统独立评审 — 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` 函数 **现象**: ```csharp // 编辑器 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` > 格子创建分支 **现象**: ```csharp 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 行 **现象**: ```csharp var mapSvc = ServiceLocator.GetOrDefault(); // 每次 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 层职责,在本模块范围外)。