# 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 分支: ```csharp // 当前代码(遗漏 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` **现象**: ```csharp _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 无探索进度脏检查(每次事件都完整重算)。