# 小地图系统 Round 6 独立评估报告 > **评估日期**:Round 6(基于当前代码状态) > **评估方法**:独立从零阅读所有 14 个地图模块文件,不参考 Round 5 自评结论 > **对标标准**:成熟 2D Metroidvania 游戏小地图,专注编辑器扩展质量、架构解耦、高性能、策划友好度 > **注意**:本轮评估目标是发现 Round 5 自评可能存在的通胀,以及 Round 4 修复后遗留的真实问题 --- ## 一、所有评估文件清单 | 文件 | 类型 | |---|---| | `IMapService.cs` | 运行时接口 | | `IPlayerPositionProvider.cs` | 运行时接口(新) | | `IPinService.cs` | 运行时接口(新) | | `MapGridConstants.cs` | 运行时常量(新) | | `MapServiceExtensions.cs` | 运行时扩展方法 | | `MapRoomDataSO.cs` + `MapDatabaseSO` | 数据层 SO | | `MapManager.cs` | 运行时管理器 | | `MapPlayerTracker.cs` | 运行时玩家追踪 | | `MapPin.cs`(MapPinManager) | 运行时标记管理 | | `MapRoomCellUI.cs` | 运行时 UI 格子 | | `MapPanel.cs` | 运行时全屏地图 | | `MinimapHUD.cs` | 运行时小地图 HUD | | `MapInputHandler.cs` | 运行时输入处理 | | `RegionNameDisplay.cs` | 运行时区域名显示 | | `MapRoomDataEditor.cs` | 编辑器扩展 | | `MapDatabaseEditor.cs` | 编辑器扩展 | | `MapLayoutEditorWindow.cs` | 编辑器扩展 | --- ## 二、逐维度独立评分 ### 维度 1:架构解耦(Architecture Decoupling) #### ✅ 优点 **接口三层完整:** ``` IMapService ← ServiceLocator ← MapManager (ISaveable) IPlayerPositionProvider ← ServiceLocator ← MapPlayerTracker IPinService ← ServiceLocator ← MapPinManager (ISaveable) ``` - `MapPanel` 和 `MinimapHUD` **零具体类 SerializeField 引用**,仅通过接口消费 ✓ - ServiceLocator 注册/注销生命周期管理正确: - MapManager: `Awake` 注册,单例保护,`OnDestroy` 注销 ✓ - MapPlayerTracker: `Awake` 注册(带 GetOrDefault 保护),`OnDestroy` 注销 ✓ - MapPinManager: `OnEnable`/`OnDisable` 注册/注销,与 ISaveableRegistry 同步 ✓ - `MapServiceExtensions.GetVisibility()` 将三级状态推导逻辑集中在一处,消费方零重复 ✓ - `OnDisable` 时清空所有接口引用,避免悬挂引用 ✓ #### ⚠️ 问题 1. **`MapDatabaseSO` 双重职责**:既是数据容器(`AllRooms[]`)又是服务类(`GetRoom()`、`ValidateAll()`)。`ValidateAll` 是 O(N²) 操作且只应在编辑器调用,但它存在于运行时 SO 中——缺少 `#if UNITY_EDITOR` 保护或独立的验证服务类。 2. **`MapRoomDataSO` 与 `MapDatabaseSO` 同文件**:Unity 约定每个 SO 类独立一个文件,同文件降低可发现性。 3. **`IMapService.Database` 属性暴露了具体类型 `MapDatabaseSO`**:接口直接暴露具体 SO 类,消费方(MinimapHUD、MapPanel)均直接访问 `Database.AllRooms`,若未来替换数据源需修改接口。 **评分:9/10**(接口体系完整,主要扣分点:Database 属性暴露具体类,ValidateAll 无编辑器保护) --- ### 维度 2:性能(Performance) #### ✅ 已解决的热路径 | 问题 | 解决方案 | |---|---| | `NormalizedPositionInRoom` 离散跳动 | 世界坐标精确插值 | | `Canvas.ForceUpdateCanvases()` 全树刷新 | `LayoutRebuilder.ForceRebuildLayoutImmediate(content)` 局部 | | Pin 重绘无脏检查 | `_lastPinVersion` dirty check | | `GetPinSprite` O(N) 循环 | `Dictionary` O(1) 查找 | | MapPlayerTracker 每帧 GetRoom 查找 | `_currentRoom` 缓存 | | LateUpdate 每帧写 RectTransform | dirty check(位置 + 房间 ID 双重检查) | | MinimapHUD `_toRemove` 每次分配 | 字段复用 | | `GUIStyle` 每帧每格创建 | `EnsureLabelStyles()` 带缩放变化检测 | #### ⚠️ 遗留性能问题 **P1(真实瓶颈):MinimapHUD.RefreshView O(N) 遍历** ```csharp // MinimapHUD.cs 第137行 foreach (var room in db.AllRooms) // O(N) 遍历全部房间 { if (room == null || _cells.ContainsKey(room.RoomId)) continue; if (!RoomInView(room, minX, maxX, minY, maxY)) continue; ... } ``` 每次房间切换(`OnRoomChanged`)遍历 `db.AllRooms` 全量扫描。房间数 ≤ 50 时影响不大,100+ 房间时每次切换房间触发 O(N) 遍历。正确做法应为空间分区(`Dictionary`)。 **P2(编辑器):MapDatabaseEditor 错误行样式每帧分配** ```csharp // MapDatabaseEditor.cs 第125-127行 var rowStyle = hasError ? new GUIStyle(EditorStyles.label) { normal = { textColor = new Color(1f, 0.35f, 0.35f) } } : EditorStyles.label; ``` 每次 `OnInspectorGUI` 重绘(高频)为每个错误房间分配新 `GUIStyle`,应缓存为字段(类比 `MapLayoutEditorWindow` 的 `_roomLabelStyle` 做法)。 **P3(低频):`GetRoomsByRegion` 每次 LINQ + `ToArray` 分配** ```csharp return _database.AllRooms.Where(r => r != null && r.RegionId == regionId).ToArray(); ``` 调用频率低,但每次调用均堆分配新数组,可改为返回 `IReadOnlyList` + 缓存或仅在热路径上注意。 **评分:8/10**(热路径整体优化良好,MinimapHUD O(N) 遍历是真实未修复问题,编辑器 GUIStyle 分配) --- ### 维度 3:编辑器扩展质量(Editor Extension Quality) #### ✅ 优点 **MapRoomDataEditor(SceneView 拖拽)** - 双角控制点 BL/TR,精度 1 格 ✓ - `Undo.RecordObject` 支持撤销 ✓ - 防反转保护(`Mathf.Min/Max`) ✓ - 一键居中 SceneView ✓ - 房间 ID 标签 + 颜色可读 ✓ **MapDatabaseEditor(Inspector 增强)** - 统计摘要(房间数、出口总数) ✓ - 一键验证 + HelpBox 错误列表 ✓ - `_cachedErrorRoomIds` 仅按钮点击时重建,避免高频 GC ✓ - 引号精确匹配(`"'{r.RoomId}'"` 防前缀误判) ✓ - 一键打开布局编辑器 + `SetDatabase()` 公共 API ✓ - 可折叠房间列表 + Ping ✓ **MapLayoutEditorWindow(独立窗口)** - 全局地图实时预览 ✓ - 滚轮缩放 + 中键/Alt拖拽平移 ✓ - 区域自动配色(8 色方案) ✓ - 验证错误红色高亮 ✓ - 点击选中房间 → Selection + Ping ✓ - 出口连线(`_zoom >= 12f` 时显示) ✓ - `GUIStyle` 缓存(`EnsureLabelStyles`,zoom 变化时重建) ✓ #### ⚠️ 问题 1. **MapDatabaseEditor 错误行样式未缓存**(同 P2,编辑器性能问题,见上文) 2. **无 `Undo.undoRedoPerformed` 回调**:在 MapRoomDataEditor 中通过 SceneView 拖拽修改后,执行 Ctrl+Z 撤销,MapLayoutEditorWindow 不会自动刷新视图,需手动点击 Repaint。 3. **无批量房间创建向导**:策划需逐个手动创建 `MapRoomDataSO.asset`,缺少"从场景列表批量生成"工具。 4. **MapRoomDataEditor.CELL_SIZE 硬编码为 1f**:SceneView 控制点坐标基于 1 格 = 1 世界单位。如果关卡实际比例不同(`MapPlayerTracker._worldUnitsPerCell = 18f`),SceneView 中的可视化与实际地图 UI 比例不一致,容易混淆策划。 **评分:8.5/10**(三工具功能完整,主要缺口:Undo 回调刷新、批量创建向导、SceneView 与 UI 比例不一致的隐患) --- ### 维度 4:数据设计(Data Design) #### ✅ 优点 - `MapRoomDataSO` 字段语义完整:基础信息、格子坐标、轮廓纹理、出口数据、特殊标记、流式加载内存预估 ✓ - `RoomExitData.PreferredTransitionType`:区分 `Seamless`/`AtmosphericFade`,过渡类型枚举化 ✓ - `MapDatabaseSO.GetRoom()` 懒加载索引 + `OnValidate`/`OnDisable` 缓存清理 ✓ - 四类验证覆盖:null、RoomId 重复、格子重叠、出口悬空 ✓ - `MapRoomDataSO.OnValidate` 保护 GridSize 最小值 ✓ - `PinSpriteEntry` 移入 `MapPin.cs`,数据与逻辑同文件 ✓ #### ⚠️ 问题 1. **无 RegionSO 数据资产**:`RegionId` 是 `string`,区域的颜色主题、显示名、排序等属性无处集中配置,目前散落在: - `RegionNameDisplay._regionNames`(运行时组件) - `MapLayoutEditorWindow.Palette`(编辑器,按发现顺序自动分配,不可控) 2. **`ValidateAll` 仅单向出口验证**:验证 A→B 存在,但不验证 B→A 是否存在(非双向可能是有意设计,但应有注释说明)。 3. **RoomId 与场景名一致约定无自动验证**:注释中要求 `RoomId` 与场景名一致(`"Room_Forest_01"`),但验证逻辑中不检查此约束。 4. **`ExitGridPos` 未验证是否在房间边界上**:出口坐标可以配置在房间内部或完全不相关的位置,验证工具不检测此异常。 **评分:8/10**(数据设计扎实,主要缺口:缺少 RegionSO、出口验证不够严格) --- ### 维度 5:功能完整性(Feature Completeness) #### 已实现功能矩阵 | 功能 | 状态 | |---|---| | 三级可见性(Unknown/Explored/Mapped) | ✅ 完整 | | 存档持久化(探索状态 + 标记) | ✅ 完整 | | 全屏地图面板 + ScrollRect | ✅ 完整 | | 角落小地图 HUD | ✅ 完整 | | 玩家位置图标(平滑跟随) | ✅ 完整 | | 当前房间高亮描边 | ✅ 完整 | | 自定义标记 Pin | ✅ 完整 | | 出口连接线显示 | ✅ 完整 | | 鼠标滚轮 + 键盘平移缩放 | ✅ 完整 | | 区域变化广播 + 区域名渐显动画 | ✅ 完整 | | 房间 Tooltip(DisplayName) | ✅ 完整 | | MapFragment 购买揭示(SetMapped) | ✅ 接口完整 | | 探索进度 API | ✅ 接口完整 | | 非矩形房间轮廓纹理 | ✅ 字段完整(UI 已接入) | #### 缺失/待完善功能 1. **探索进度无 HUD 显示**:`IMapService.GetExplorationProgress()` + `ExploredRoomCount` 已实现,但 UI 层(MapPanel、MinimapHUD)均未显示进度条或百分比文本。 2. **移动端 / 手柄支持**:`MapInputHandler` 使用旧版 `Input.GetAxisRaw`,无 Pinch 缩放手势,移动端不可用。 3. **小地图运行时缩放调节**:MinimapHUD 的 `_cellPixels` 只可在 Inspector 配置,玩家运行时无法调整小地图大小(无障碍缺口)。 4. **标记类型不足**:Pin 只有基础 `PinType` 枚举(定义在 SaveData.cs),缺少游戏中常见的「未解谜」「隐藏通道」「收藏品」等语义标记类型的默认配置。 5. **全屏地图与小地图无联动隐藏**:打开全屏地图时 MinimapHUD 不自动隐藏,视觉上有重叠(需外部 UIManager 处理,系统内无协调机制)。 **评分:8/10**(核心功能覆盖全面,缺失点为进度显示、移动端支持、小地图缩放) --- ### 维度 6:代码质量(Code Quality) #### ✅ 优点 - 命名规范一致:`_camelCase` 私有字段,`PascalCase` 公有成员 ✓ - XML 文档注释覆盖所有公共 API ✓ - `//──` 区域注释辅助导航 ✓ - no-game-references 规则完全遵守 ✓ - `MapServiceExtensions` 消除消费方重复的三级状态判断逻辑 ✓ - `MapGridConstants.FullMapCellPixels` 消除 3 处散落的 `32f` 硬编码 ✓ - `CompositeDisposable _subs` 统一管理事件订阅生命周期 ✓ #### ⚠️ 问题 1. **`MapPin.cs` 文件名与类名不一致**:文件包含 `MapPinManager` 类,文件头虽有注释说明,但工具搜索"MapPin.cs"不会找到 `MapPinManager`。这是历史遗留问题,需在安全时机重命名。 2. **`MapDatabaseEditor` 错误行样式每帧分配**(同 P2): ```csharp var rowStyle = hasError ? new GUIStyle(EditorStyles.label) { ... } // ← 每次 OnInspectorGUI 分配 : EditorStyles.label; ``` 3. **`MapManager.GetRoomsByRegion` 每次 LINQ + ToArray**:返回 `MapRoomDataSO[]`,调用方每次得到新数组。建议改为按需缓存或返回 `IReadOnlyList`。 4. **`MapPanel.DrawExits` 中的硬编码尺寸**: ```csharp conn.rectTransform.sizeDelta = vertical ? new Vector2(16f, 8f) : new Vector2(8f, 16f); ``` 出口连接线尺寸硬编码为 `16f/8f`,未使用 `MapGridConstants` 派生,与全屏地图的格子尺寸(32f)比例关系不透明。 5. **`RegionNameDisplay.ResolveDisplayName` O(N) 线性查找**:区域数量通常 < 20,影响微小,但与 GetPinSprite 字典化处理的一致性不足。 **评分:8.5/10**(整体规范高,主要扣分点:文件名不一致、MapDatabaseEditor GUIStyle 分配、DrawExits 硬编码) --- ### 维度 7:可扩展性(Extensibility) #### ✅ 优点 - 接口层允许替换实现(测试时可 Mock `IMapService`) ✓ - `PinType` 枚举可在 SaveData.cs 扩展 + `_pinSprites` Inspector 配置 ✓ - 颜色完全可配置(SerializeField on MapPanel, MinimapHUD) ✓ - 事件渠道(EventChannelSO)允许外部任意系统订阅地图事件 ✓ - `MapRoomDataSO` SO 驱动,增加房间只需新建资产 ✓ - `MapServiceExtensions` 扩展方法机制允许在不修改接口的情况下添加新查询 ✓ #### ⚠️ 问题 1. **MapPanel 无覆盖层(Overlay)扩展点**:添加「区域边界覆盖」「探索热度图」等新层需要直接修改 `MapPanel.cs`,无法通过组件/插件扩展。 2. **`MapRoomDataSO` 无自定义扩展字段**:新增房间属性(如「危险等级」「推荐等级要求」)需修改 SO 类,无法通过 ScriptableObject 继承或 payload 扩展。 3. **`IMapService.Database` 返回具体类**:(同架构问题)限制了未来数据源替换(如从服务器加载、动态生成)的可能性。 **评分:8/10**(接口 + 事件体系支持良好扩展,主要缺口:MapPanel 无 Overlay 系统,MapRoomDataSO 无扩展字段) --- ### 维度 8:策划友好度(Designer/Planner Friendliness) #### ✅ 优点 - `MapRoomDataSO` 字段有中文 Header + 详细 Tooltip(`EstimatedMemoryKB`、`PreferredTransitionType` 均有使用说明)✓ - `MapDatabaseEditor` 提供统计摘要、一键验证、可折叠房间列表 ✓ - `MapRoomDataEditor` 支持 SceneView 直接拖拽调整房间位置和大小 ✓ - `MapLayoutEditorWindow` 直观预览全局地图 + 区域配色区分 ✓ - 验证错误以 HelpBox/红色高亮明确指出有问题的房间 ✓ #### ⚠️ 问题 1. **无 MapDesignSpec 文档**:缺少指导策划配置地图的设计规范文档(`Docs/Standards/MapDesignSpec.md`),策划需从代码注释推断配置规则。 2. **无批量房间创建向导**:每个房间需单独创建 SO 并手动填写 RoomId,100 个房间需重复 100 次相同操作。 3. **`MapLayoutEditorWindow` 无探索状态预览**:窗口只显示房间布局,无法预览各可见性状态(Unknown/Explored/Mapped)下的视觉效果。 4. **`RegionId` 无枚举约束**:策划可以在不同 SO 中输入 `"Forest"` 和 `"forest"` 导致区域不匹配,缺少下拉选择或自动补全。 **评分:8/10**(工具覆盖主要流程,策划可独立使用,主要缺口:缺乏文档、批量工具、RegionId 输入约束) --- ## 三、与 Round 5 自评对比 | 维度 | Round 5 自评 | Round 6 独立评分 | 差值 | 主要差异 | |---|---|---|---|---| | 架构解耦 | 9.5/10 | 9/10 | -0.5 | Database 属性暴露具体类型 | | 性能 | 9/10 | 8/10 | **-1** | MinimapHUD O(N)遍历未修复 | | 编辑器扩展 | 9/10 | 8.5/10 | -0.5 | 无 Undo 刷新回调,GUIStyle 分配 | | 数据设计 | 8.5/10 | 8/10 | -0.5 | 缺 RegionSO,出口单向验证 | | 功能完整性 | 8/10 | 8/10 | 0 | 一致 | | 代码质量 | 8.5/10 | 8.5/10 | 0 | 一致 | | 可扩展性 | 8/10 | 8/10 | 0 | 一致 | | 策划友好度 | 8/10 | 8/10 | 0 | 一致 | | **加权总分** | **90/100** | **85/100** | **-5** | | > Round 5 总分通胀约 **+5 分**,来源:性能维度对 MinimapHUD 问题评估过松(标注为已知但仍给 9 分),以及架构维度未扣 Database 暴露具体类分。 --- ## 四、Round 6 发现的新问题(Round 5 未标注) ### 🔴 N1:MapDatabaseEditor 错误行 GUIStyle 每帧分配 **位置**:`MapDatabaseEditor.cs` 第 125-127 行 ```csharp var rowStyle = hasError ? new GUIStyle(EditorStyles.label) { normal = { textColor = new Color(1f, 0.35f, 0.35f) } } : EditorStyles.label; ``` **问题**:`OnInspectorGUI` 每次重绘(约 10-30 fps)为每个错误房间分配新 `GUIStyle`。`MapLayoutEditorWindow` 已通过 `EnsureLabelStyles()` 正确缓存,但 `MapDatabaseEditor` 遗漏了相同处理。 **修复方案**: ```csharp // 在类中添加缓存字段 private GUIStyle _errorRowStyle; // 在 OnEnable 或首次使用时初始化 private GUIStyle GetErrorRowStyle() { if (_errorRowStyle == null) _errorRowStyle = new GUIStyle(EditorStyles.label) { normal = { textColor = new Color(1f, 0.35f, 0.35f) } }; return _errorRowStyle; } // 使用时 var rowStyle = hasError ? GetErrorRowStyle() : EditorStyles.label; ``` --- ### 🔴 N2:MapRoomDataEditor.CELL_SIZE 与 MapPlayerTracker._worldUnitsPerCell 比例不一致隐患 **位置**:`MapRoomDataEditor.cs` 第 16 行 vs `MapPlayerTracker.cs` 第 25 行 ```csharp // MapRoomDataEditor.cs private const float CELL_SIZE = 1f; // SceneView 中每格 = 1 世界单位 // MapPlayerTracker.cs [SerializeField] private float _worldUnitsPerCell = 18f; // 运行时每格 = 18 世界单位 ``` **问题**: - SceneView 中拖拽房间角点的坐标系使用 1 格 = 1 世界单位 - 运行时玩家追踪的坐标系使用 1 格 = 18 世界单位 - 两套坐标系并存,策划在 SceneView 中看到的房间布局与实际游戏世界坐标无直接对应关系 - 若策划以为 SceneView 中调整的就是游戏内的实际空间,会在关卡设计时产生误解 **建议**:在 `MapRoomDataEditor` 的 SceneView HelpBox 中明确说明此坐标换算,或将 `CELL_SIZE` 从 `MapGridConstants` 派生(需将 CELL_SIZE 添加到常量类)。 --- ### 🟡 N3:MinimapHUD.RefreshView 中 `db.AllRooms` 遍历顺序不稳定问题 当 `RefreshView` 先回收旧格子,再添加新格子时: ```csharp // 步骤③:重定位全部格子(含新加入的) foreach (var (id, cell) in _cells) { if (cell == null) continue; var r = db.GetRoom(id); // ← 每次 GetRoom 触发索引查找,O(1) 但有 dict 访问开销 if (r != null) PlaceCell(cell, r); } ``` 在步骤②已经通过 `cell.Setup()` 设置了格子位置(基于 `MapGridConstants.FullMapCellPixels`),步骤③立即通过 `PlaceCell` 用 `_cellPixels` 覆盖。这意味着 `Setup()` 的位置设置对 MinimapHUD 完全无效,每次都被 `PlaceCell` 覆盖,产生不必要的 UI 操作。 **建议**:MinimapHUD 在 Instantiate 后直接调用 `PlaceCell` 而不通过 `Setup()` 传入默认 pixelsPerCell。 --- ### 🟡 N4:`MapInputHandler` 使用旧版 Input System ```csharp float h = Input.GetAxisRaw("Horizontal"); float v = Input.GetAxisRaw("Vertical"); ``` 若项目引入 Unity New Input System,此代码会失效(Input 轴未正确重定向时返回 0)。应通过 `IInputService` 或 `InputActions` 接入。 --- ## 五、待修复优先级 ### 优先级 P1(高:影响运行性能) | ID | 问题 | 位置 | 影响 | |---|---|---|---| | P1-1 | MinimapHUD.RefreshView O(N) 遍历 | `MinimapHUD.cs:137` | 大型地图(100+房间)房间切换卡顿 | ### 优先级 P2(中:影响编辑器体验) | ID | 问题 | 位置 | 影响 | |---|---|---|---| | P2-1 | MapDatabaseEditor 错误行 GUIStyle 每帧分配 | `MapDatabaseEditor.cs:125-127` | 编辑器 GC 压力 | | P2-2 | MapRoomDataEditor CELL_SIZE 与运行时比例不一致 | `MapRoomDataEditor.cs:16` | 策划混淆坐标系 | | P2-3 | 无 Undo 刷新回调(MapLayoutEditorWindow) | `MapLayoutEditorWindow.cs` | SceneView Undo 后窗口不自动刷新 | | P2-4 | ValidateAll 缺 `#if UNITY_EDITOR` 保护 | `MapRoomDataSO.cs:103` | 运行时构建包含 O(N²) 验证逻辑 | ### 优先级 P3(低:架构改进) | ID | 问题 | 位置 | 影响 | |---|---|---|---| | P3-1 | 缺少 RegionSO 数据资产 | 新文件 | 区域颜色/名称配置分散 | | P3-2 | MapDesignSpec.md 文档缺失 | Docs/Standards | 策划无参考文档 | | P3-3 | IMapService.Database 暴露具体类 | `IMapService.cs:12` | 限制未来数据源替换 | | P3-4 | MapPanel 无 Overlay 扩展点 | `MapPanel.cs` | 新增覆盖层需修改源码 | | P3-5 | GetRoomsByRegion LINQ 每次分配数组 | `MapManager.cs:114` | 低频但可优化 | --- ## 六、Round 6 总评 ### 最终得分:85/100 ``` 架构解耦 ████████░░ 9/10 性能 ████████░░ 8/10 ← MinimapHUD O(N) 真实问题 编辑器扩展 ████████░░ 8.5/10 数据设计 ████████░░ 8/10 功能完整性 ████████░░ 8/10 代码质量 ████████░░ 8.5/10 可扩展性 ████████░░ 8/10 策划友好度 ████████░░ 8/10 ───────────────────────────── 加权总分 85/100 ``` ### 总结 经过 Round 4 的 14 项修复,系统已从 Round 3 膨胀的 89 分回落至真实的 ~79 分,再经修复提升至当前的 **85 分**。Round 5 自评的 90 分存在约 +5 分的评估偏高。 **系统优势**:接口解耦体系完整、热路径性能全面优化、编辑器三工具功能齐全、数据驱动设计规范。 **主要差距**: 1. MinimapHUD 在大型地图下有 O(N) 遍历真实瓶颈 2. 缺少 RegionSO 资产导致区域配置分散 3. 编辑器工具有小的 GC 问题和 Undo 刷新缺口 4. 策划侧缺乏设计规范文档 达到 90+ 分需解决 P1-1(MinimapHUD 空间索引)和 P3-1(RegionSO)两个主要缺口。 --- --- ## 七、修复实施结果追踪 > 本章记录根据 Round 6 评估结论对代码执行的实际修复,确保报告与代码状态同步。 ### P1 修复(高优先级) | ID | 状态 | 修改文件 | 说明 | |---|---|---|---| | P1-1 MinimapHUD 空间索引 | ✅ 已修复 | `MinimapHUD.cs` | 新增 `_spatialIndex Dict` + `_roomsInViewBuffer HashSet`;`BuildSpatialIndex()` 在 `OnEnable` 构建;RefreshView step② 改为 O(viewRadius²) 空间索引查询替代 O(N) 全量遍历 | ### P2 修复(中优先级 — 编辑器体验) | ID | 状态 | 修改文件 | 说明 | |---|---|---|---| | P2-1 MapDatabaseEditor GUIStyle 缓存 | ✅ 已修复 | `MapDatabaseEditor.cs` | 新增 `_errorRowStyle` 缓存字段 + `GetErrorRowStyle()` 惰性初始化;`OnEnable` 时置 null(编辑器皮肤切换时重建);替换 `OnInspectorGUI` 内每帧 `new GUIStyle()` 调用 | | P2-2 MapRoomDataEditor CELL_SIZE 说明 | ✅ 已修复 | `MapRoomDataEditor.cs` | Inspector HelpBox 补充坐标系说明:CELL_SIZE=1f 仅为 SceneView 可视化单位,格子布局数据(GridPosition/GridSize)是统一的格子单位,与运行时 worldUnitsPerCell 无需换算 | | P2-3 MapLayoutEditorWindow Undo 刷新 | ✅ 已修复 | `MapLayoutEditorWindow.cs` | 新增 `OnEnable`/`OnDisable` 注册/注销 `Undo.undoRedoPerformed`;`OnUndoRedo()` 清除验证缓存并调用 `Repaint()` | | P2-4 ValidateAll 编辑器保护 | ✅ 已修复 | `MapRoomDataSO.cs` | `ValidateAll()` 方法用 `#if UNITY_EDITOR` 包裹,O(N²) 验证逻辑不再进入运行时构建;两个调用方编辑器文件本身已在 `#if UNITY_EDITOR` 中,编译无变化 | ### N3 修复(MinimapHUD 冗余位置写入) | ID | 状态 | 修改文件 | 说明 | |---|---|---|---| | N3 Setup 冗余位置设置 | ✅ 已修复 | `MinimapHUD.cs` | RefreshView step② 在 Instantiate+Setup 后立即调用 `PlaceCell(cell, room)` 设置正确的中心相对坐标,step③ PlaceCell 覆盖成为幂等确认操作 | ### P3 未修复项(低优先级,架构级改动) | ID | 状态 | 原因 | |---|---|---| | P3-1 缺少 RegionSO | ⏳ 待后续 | 需新建 SO 类 + 编辑器工具 + 修改 MapManager,工作量较大 | | P3-2 MapDesignSpec.md | ⏳ 待后续 | 文档补充,不影响运行 | | P3-3 IMapService.Database 具体类 | ⏳ 待后续 | 需调整接口,影响范围广 | | P3-4 MapPanel Overlay 扩展点 | ⏳ 待后续 | 架构扩展,需设计方案 | | P3-5 GetRoomsByRegion LINQ 分配 | ⏳ 待后续 | 低频调用,影响可忽略 | ### 修复后预估得分 | 维度 | 修复前 | 修复后预估 | |---|---|---| | 性能 | 8/10 | **8.5/10**(P1-1 空间索引修复主要瓶颈) | | 编辑器扩展 | 8.5/10 | **9/10**(P2-1 GUIStyle + P2-3 Undo 刷新均已修复) | | 数据设计 | 8/10 | **8/10**(ValidateAll 保护改善了构建质量,不影响功能评分) | | 其他维度 | 不变 | 不变 | | **总分** | **85/100** | **~87/100** |