- 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.
472 lines
21 KiB
Markdown
472 lines
21 KiB
Markdown
# 小地图系统 Round 11 独立评估报告
|
||
|
||
> 评估时间:2026-05-25
|
||
> 基准版本:R10 全部修复落地后当前 HEAD
|
||
> 评估范围:`Assets/_Game/Scripts/World/Map/` + `Assets/_Game/Scripts/Editor/World/Map/`
|
||
> 对标标准:成熟 2D 银河恶魔城游戏标准(高性能、高解耦、策划友好、编辑器一流)
|
||
|
||
---
|
||
|
||
## 第 1 章:整体评分
|
||
|
||
| 维度 | 分值(满 10) | 较 R10 |
|
||
|---|---|---|
|
||
| 架构解耦 | 8.5 | ↑0.5(事件语义分离完成) |
|
||
| 数据设计 | 8.5 | ↑0(稳定) |
|
||
| 运行时性能 | 8.5 | ↑0.3(Pin 池 + Cell 保留落地) |
|
||
| 编辑器扩展 | 8.0 | ↑0.5(拖拽冲突可视化、IsDefault) |
|
||
| 策划友好性 | 7.5 | ↑0(仍缺 DisplayName 本地化) |
|
||
| 功能完整性 | 8.5 | ↑0(稳定) |
|
||
| 鲁棒性 | 7.5 | ↓0.5(发现 N11 部分订阅 Bug) |
|
||
| 可扩展性 | 8.5 | ↑0.3(SetMappedBatch、OnRoomMapped) |
|
||
|
||
**加权综合得分:85.6 / 100(B+)**
|
||
> 注:R10 修复整体质量优秀;本轮发现 N1 MinimapHUD 部分订阅 Bug(P1 级别真实缺陷),导致鲁棒性维度扣分,综合分低于 R10 预估的 92 分。
|
||
|
||
---
|
||
|
||
## 第 2 章:系统亮点
|
||
|
||
### 2.1 接口与事件设计(9/10)
|
||
- `IMapService` 完整定义了三个语义明确的事件:`OnDatabaseChanged`(结构变更)/ `OnExplorationChanged`(探索进度)/ `OnRoomMapped`(单房间解锁)。
|
||
- 消费方(MapPanel、MinimapHUD)通过接口与 ServiceLocator 完全解耦,不持有任何具体 MonoBehaviour 引用。
|
||
- `MapServiceExtensions.GetVisibility` 集中三级可见性推导逻辑,避免分散重复。
|
||
|
||
### 2.2 空间索引共享(9/10)
|
||
- `MapDatabaseSO.GetRoomIdAtCell(Vector2Int)` 惰性构建一次,供 `MapPlayerTracker` / `MinimapHUD.RefreshView` 共享,O(1) 格子查找。
|
||
- `InvalidateIndex` 在结构变更时统一失效,不存在缓存过期风险。
|
||
|
||
### 2.3 MinimapHUD 增量刷新(8.5/10)
|
||
- `RefreshView` 为 O(viewRadius²) 而非 O(allRooms),大地图下效果显著。
|
||
- 回收/新建格子避免全量重建,`_toRemove` / `_roomsInViewBuffer` 列表复用消除高频 GC。
|
||
|
||
### 2.4 编辑器工具套件(8/10)
|
||
- `MapLayoutEditorWindow`:格子布局预览 + 区域着色 + 拖拽移房 + 冲突可视化(R10-N5)+ 搜索/图例 + 验证 + Play Mode 玩家位置。
|
||
- `MapRoomDataEditor`:Scene View 双角控制点直接拖拽,策划可在场景中直观编辑房间尺寸。
|
||
- `MapRoomAutoRegister`:新建 SO 自动追加到默认 Database,消灭策划忘记注册的问题。
|
||
|
||
### 2.5 数据兼容性保障(9/10)
|
||
- `[FormerlySerializedAs("AllRooms")]` 确保 `_allRooms` 字段重命名后现有 `.asset` 不丢失数据。
|
||
- `EditorSetRooms` 专用写入器防止外部代码绕过封装直接赋值。
|
||
|
||
---
|
||
|
||
## 第 3 章:新发现问题(R11-N1 ~ N12)
|
||
|
||
### R11-N1 ★P1★ — MinimapHUD `_subscribed` 标志导致部分订阅场景下事件永不触发
|
||
|
||
**文件:** `MinimapHUD.cs` → `SubscribeServices()`
|
||
|
||
**现象:**
|
||
```csharp
|
||
private void SubscribeServices()
|
||
{
|
||
_mapSvc ??= ServiceLocator.GetOrDefault<IMapService>();
|
||
_playerProvider ??= ServiceLocator.GetOrDefault<IPlayerPositionProvider>();
|
||
_pinService ??= ServiceLocator.GetOrDefault<IPinService>();
|
||
if (_subscribed) return; // ← 提前 return 阻断后续
|
||
if (_mapSvc == null && _playerProvider == null) return;
|
||
if (_playerProvider != null)
|
||
_playerProvider.OnRoomChanged += OnRoomChanged;
|
||
if (_mapSvc != null)
|
||
{
|
||
_mapSvc.OnDatabaseChanged += OnDatabaseChanged;
|
||
_mapSvc.OnExplorationChanged += OnExplorationChanged;
|
||
}
|
||
_subscribed = true; // ← 仅当上方至少一个服务非 null 时才置位
|
||
}
|
||
```
|
||
|
||
**具体 Bug:**
|
||
场景——`_playerProvider` 在 Awake 时已注册(优先 ExecutionOrder),但 `_mapSvc` 尚未就绪:
|
||
1. 第一次调用:`_playerProvider` 成功,`_mapSvc == null` → 仅订阅 `OnRoomChanged`,置 `_subscribed = true`。
|
||
2. 后续调用:`_mapSvc` 现已就绪,但 `if (_subscribed) return` 提前退出,**`OnDatabaseChanged` / `OnExplorationChanged` 永远不订阅**。
|
||
3. 结果:小地图 HUD 读档后不刷新、房间解锁后不更新颜色。
|
||
|
||
**修复方案:** 改为分别追踪 `_mapSvcSubscribed` / `_playerSubscribed`,或直接仿照 `MapPanel` 的模式(每个服务独立 `if (svc == null)` 守门)。
|
||
|
||
---
|
||
|
||
### R11-N2 ★P1★ — `MapRoomDataSO.OnValidate` 重复向 `delayCall` 追加委托
|
||
|
||
**文件:** `MapRoomDataSO.cs` → `OnValidate()`
|
||
|
||
```csharp
|
||
private void OnValidate()
|
||
{
|
||
GridSize = new Vector2Int(Mathf.Max(1, GridSize.x), Mathf.Max(1, GridSize.y));
|
||
#if UNITY_EDITOR
|
||
UnityEditor.EditorApplication.delayCall += NotifyOwningDatabases; // ← 问题所在
|
||
#endif
|
||
}
|
||
```
|
||
|
||
**问题:** `delayCall` 是多播委托(`+=`)。当策划在 Inspector 中快速拖动滑条时,`OnValidate` 每帧调用一次,`NotifyOwningDatabases` 被追加数十次。该方法内部执行 `FindAssets` + `LoadAssetAtPath`(昂贵),会在下一帧批量执行导致卡顿。
|
||
|
||
**修复方案:** 先 `-=` 再 `+=`,保证同一 delayCall 序列中最多一次:
|
||
```csharp
|
||
EditorApplication.delayCall -= NotifyOwningDatabases;
|
||
EditorApplication.delayCall += NotifyOwningDatabases;
|
||
```
|
||
|
||
---
|
||
|
||
### R11-N3 ★P1★ — `MapPinManager.OnLoad` 直接赋值反序列化 List,共享 SaveData 引用
|
||
|
||
**文件:** `MapPin.cs` → `MapPinManager.OnLoad()`
|
||
|
||
```csharp
|
||
public void OnLoad(SaveData data)
|
||
{
|
||
_pins = data.Map.Pins ?? new List<MapPin>(); // ← 直接赋值,不是拷贝
|
||
PinsVersion++;
|
||
}
|
||
```
|
||
|
||
`OnSave` 做了防御性拷贝(`new List<MapPin>(_pins)`),但 `OnLoad` 反方向没有拷贝。若调用方在 `OnLoad` 后继续持有 `data` 并修改 `data.Map.Pins`,会污染 `_pins`。
|
||
|
||
**修复:**
|
||
```csharp
|
||
_pins = data.Map.Pins != null ? new List<MapPin>(data.Map.Pins) : new List<MapPin>();
|
||
```
|
||
|
||
---
|
||
|
||
### R11-N4 ★P1★ — `MapPanel.CenterOnCurrentRoom` 对整个 content 节点调用 `ForceRebuildLayoutImmediate`
|
||
|
||
**文件:** `MapPanel.cs` → `CenterOnCurrentRoom()`
|
||
|
||
```csharp
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(_scrollRect.content);
|
||
```
|
||
|
||
`ForceRebuildLayoutImmediate` 会递归重建参数节点及其所有子节点的 Layout。`_scrollRect.content` 下有所有 MapRoomCellUI 实例,重建代价随房间数线性增长(N 房间 = N 次 layout 计算)。面板每次 `OnEnable` 时执行一次,常规用法中可接受;但若项目规模扩展到 200+ 房间,此处会成为明显延迟点。
|
||
|
||
**建议:** 只有在 content 布局确实发生变化时(BuildGrid 之后)才 ForceRebuild;若 ScrollRect 没有使用 LayoutGroup,可改为直接计算 normalizedPosition,完全跳过 ForceRebuildLayoutImmediate。
|
||
|
||
---
|
||
|
||
### R11-N5 ★P2★ — `MinimapHUD` 对 `MapRoomCellUI` 无对象池,跨房间时 GC 抖动
|
||
|
||
**文件:** `MinimapHUD.cs` → `RefreshView()` → cell 回收段
|
||
|
||
```csharp
|
||
if (cell != null) Destroy(cell.gameObject); // ← 销毁而非入池
|
||
```
|
||
|
||
MinimapHUD 的 `RefreshView` 在玩家跨越房间边界时,会销毁视野外的 `MapRoomCellUI` GameObject 并重新实例化新进入视野的格子。
|
||
- 典型场景(走廊穿梭):每次房间切换约销毁/创建 3-8 个 Cell GameObject,频率可达 1-2 次/秒。
|
||
- Pin 已有对象池,但 Cell 没有,导致一定 GC 压力。
|
||
|
||
**建议:** 为 `MapRoomCellUI` 建立 `Stack<MapRoomCellUI> _cellPool`,回收时 `SetActive(false)` 入池,需要时出池重置,与 Pin 池保持一致。
|
||
|
||
---
|
||
|
||
### R11-N6 ★P2★ — `MapManager.GetRoomsByRegion` 每次调用都分配新数组
|
||
|
||
**文件:** `MapManager.cs`
|
||
|
||
```csharp
|
||
public MapRoomDataSO[] GetRoomsByRegion(string regionId)
|
||
=> _database.AllRooms.Where(r => r != null && r.RegionId == regionId).ToArray();
|
||
```
|
||
|
||
每次调用分配 LINQ 枚举器 + 结果数组。若调用方(如 MapPanel 地区筛选、成就系统)在 Update 中使用,会造成 GC。
|
||
|
||
**建议:** 加结果缓存(Dictionary<string, MapRoomDataSO[]>),在 `NotifyDatabaseChanged` 时失效。
|
||
|
||
---
|
||
|
||
### R11-N7 ★P2★ — `MapLayoutEditorWindow` 不监听外部资产变更
|
||
|
||
**文件:** `MapLayoutEditorWindow.cs`
|
||
|
||
窗口打开后:
|
||
- 若从代码/其他窗口修改 `MapDatabaseSO`(如 MapDatabaseEditor 的 Validate 按钮),布局窗口不自动刷新,需用户手动交互。
|
||
- `Undo.undoRedoPerformed` 正确注册,但外部变更(`EditorUtility.SetDirty` 后保存、脚本修改资产)不触发 `Repaint`。
|
||
|
||
**建议:** 监听 `EditorApplication.projectWindowItemOnGUI` 或使用 `AssetDatabase.postprocessAllAssets`;或在 `OnGUI` 开头检查 database 的 `AllRooms` 数组引用变化(版本号方案)。
|
||
|
||
---
|
||
|
||
### R11-N8 ★P2★ — `MapRoomCellUI.Setup` 的 `pixelsPerCell` 参数对 MinimapHUD 调用路径存在 API 语义歧义
|
||
|
||
**文件:** `MapRoomCellUI.cs` / `MinimapHUD.cs`
|
||
|
||
```csharp
|
||
// MinimapHUD 调用路径:
|
||
cell.Setup(room, _mapSvc.GetVisibility(room.RoomId), null); // 使用默认 pixelsPerCell=32
|
||
cell.SetColors(_colorExplored, _colorMapped, _colorUnknown);
|
||
PlaceCell(cell, room); // 立即覆盖 RT.anchoredPosition 和 sizeDelta
|
||
```
|
||
|
||
`Setup` 内部已根据 `pixelsPerCell` 计算并写入了 `RT.anchoredPosition` / `RT.sizeDelta`,但 MinimapHUD 立即用 `PlaceCell` 覆盖,造成无意义的写入。`pixelsPerCell` 参数对 MinimapHUD 路径无实际效果,但 API 签名暗示它有意义,容易误导维护者。
|
||
|
||
**建议:** 在 `Setup` 中将位置/尺寸计算提取为 `SetGridLayout(room, pixelsPerCell)` 方法,MinimapHUD 调用 `Setup` 时不传位置参数,由 `PlaceCell` 统一负责布局。或简化为重载:`Setup(room, visibility, icon)` + `Setup(room, visibility, icon, pixelsPerCell)`。
|
||
|
||
---
|
||
|
||
### R11-N9 ★P2★ — `MapPlayerTracker` 假设世界原点与格子原点重合,无 WorldOffset 参数
|
||
|
||
**文件:** `MapPlayerTracker.cs`
|
||
|
||
```csharp
|
||
private Vector2Int WorldToCell(Vector2 worldPos)
|
||
=> new(Mathf.FloorToInt(worldPos.x / _worldUnitsPerCell),
|
||
Mathf.FloorToInt(worldPos.y / _worldUnitsPerCell));
|
||
```
|
||
|
||
如果关卡世界坐标原点不在 (0,0)(如整个世界在 Y=-500 以下),此计算会得到错误的格子坐标,导致玩家位置追踪完全失效。
|
||
|
||
**建议:** 增加 `[SerializeField] private Vector2 _worldOriginOffset` 字段,`WorldToCell` 先减去 `_worldOriginOffset` 再除以 `_worldUnitsPerCell`。
|
||
|
||
---
|
||
|
||
### R11-N10 ★P2★ — `MapLayoutEditorWindow.DrawExitLines` 连线使用房间中心而非实际出口格子坐标
|
||
|
||
**文件:** `MapLayoutEditorWindow.cs` → `DrawExitLines()`
|
||
|
||
```csharp
|
||
Vector2 from = GridCenterToClip(room.GridPosition + room.GridSize / 2, origin); // 房间中心
|
||
Vector2 to = GridCenterToClip(target.GridPosition + target.GridSize / 2, origin);
|
||
```
|
||
|
||
`RoomExitData` 结构中已有 `ExitGridPos` 字段(出口在格子地图上的实际位置),但 `DrawExitLines` 画的是两个房间**中心**之间的连线。对于大尺寸房间,连线起止点可能距离实际出口较远,策划无法直观判断出口对齐情况。
|
||
|
||
**建议:** 改为从 `exit.ExitGridPos` 到对应 target 房间的对应出口格子坐标,若 target 无对应出口则退化为中心连线。
|
||
|
||
---
|
||
|
||
### R11-N11 ★P2★ — `MapRoomDataSO` 公共字段缺少 RoomId 命名规则验证
|
||
|
||
**文件:** `MapRoomDataSO.cs` / `MapDatabaseSO.cs` → `ValidateAll()`
|
||
|
||
`RoomId` 字段直接用于:
|
||
1. 场景名匹配(`OnRoomEntered` 事件传入场景名)
|
||
2. Dictionary key 查找
|
||
3. 存档 HashSet 存储
|
||
|
||
目前 `ValidateAll` 检查了重复和空值,但未检查:
|
||
- 首尾空格(`" Room_A "` 与 `"Room_A"` 被视为不同但功能等效时易混淆)
|
||
- 特殊字符(`/`、`\` 等可能影响路径处理的字符)
|
||
|
||
**建议:** 在 `MapRoomDataSO.OnValidate` 中自动 `Trim()`;在 `ValidateAll` 中增加含空格/特殊字符的警告。
|
||
|
||
---
|
||
|
||
### R11-N12 ★P3★ — `MapLayoutEditorWindow.DrawExitLines` 连线在极端缩放(≤ 0°)时 `GUI.matrix` 未正确恢复
|
||
|
||
**文件:** `MapLayoutEditorWindow.cs` → `DrawLine()`
|
||
|
||
```csharp
|
||
GUIUtility.RotateAroundPivot(angle, mid);
|
||
GUI.DrawTexture(...);
|
||
GUI.matrix = prevMatrix; // 手动恢复
|
||
```
|
||
|
||
若 `DrawTexture` 抛出异常(如纹理被意外卸载),`GUI.matrix` 不会被恢复,导致整个窗口绘制出现旋转偏移。
|
||
|
||
**建议:** 使用 `using (new GUIMatrixScope(...))` 或 `try/finally` 包裹:
|
||
```csharp
|
||
var prev = GUI.matrix;
|
||
try { GUIUtility.RotateAroundPivot(angle, mid); GUI.DrawTexture(...); }
|
||
finally { GUI.matrix = prev; }
|
||
```
|
||
|
||
---
|
||
|
||
## 第 4 章:维度详细评分
|
||
|
||
### 4.1 架构解耦 — 8.5/10
|
||
|
||
**优秀:**
|
||
- IMapService 接口三个独立事件,语义清晰
|
||
- ServiceLocator 注册在 Awake/OnDestroy,生命周期正确
|
||
- MapPinManager 独立于 MapManager,通过 IPinService 解耦
|
||
- MapServiceExtensions 扩展方法集中可复用逻辑
|
||
|
||
**不足:**
|
||
- MinimapHUD `_subscribed` 标志存在部分订阅 Bug(N1 P1)
|
||
- MapPanel 仍通过 `StringEventChannelSO _onMapUpdated` 双通道接收单房间更新(OnMapUpdated + OnExplorationChanged 语义重叠但各有其用,轻微冗余)
|
||
|
||
---
|
||
|
||
### 4.2 数据设计 — 8.5/10
|
||
|
||
**优秀:**
|
||
- 三级可见性(Unknown / Explored / Mapped)精确匹配银河恶魔城标准
|
||
- MapDatabaseSO 懒构建双索引(id → data,cell → roomId),共享给所有消费方
|
||
- MapRoomDataSO.OnValidate 自动修正 GridSize 最小值
|
||
- RoomExitData 包含 TransitionType,为场景切换类型扩展预留
|
||
|
||
**不足:**
|
||
- GetRoomsByRegion 无结果缓存(N6 P2)
|
||
- DisplayName 无 i18n 路径(延续 R10-N10)
|
||
- RoomId 无命名规则强制检查(N11 P2)
|
||
|
||
---
|
||
|
||
### 4.3 运行时性能 — 8.5/10
|
||
|
||
**优秀:**
|
||
- MinimapHUD RefreshView O(viewRadius²),大地图下远快于 O(N)
|
||
- Pin 对象池(MapPanel + MinimapHUD),ClearPins = SetActive(false) 而非 Destroy
|
||
- 脏标志驱动 UI(databaseDirty / explorationDirty / viewDirty)
|
||
- LateUpdate 双重脏检查(PinsVersion + 玩家位置)
|
||
- MapDatabaseSO 空间索引 O(1) 哈希查找
|
||
|
||
**不足:**
|
||
- MinimapHUD MapRoomCellUI 无对象池(N5 P2),跨房间边界 GC 抖动
|
||
- CenterOnCurrentRoom 对 content ForceRebuildLayoutImmediate(N4 P1),大房间数时开销可见
|
||
- GetRoomsByRegion LINQ.ToArray() 无缓存(N6 P2)
|
||
|
||
---
|
||
|
||
### 4.4 编辑器扩展 — 8.0/10
|
||
|
||
**优秀:**
|
||
- MapLayoutEditorWindow 全功能:zoom/pan/drag/conflict/search/legend/validate/PlayMode 玩家点
|
||
- MapRoomDataEditor Scene View 双角控制点 + 吸附 + Undo + 居中快捷键
|
||
- MapDatabaseEditor 一键验证 + 房间列表 + 错误行红色高亮
|
||
- MapRoomAutoRegister 自动注册消除遗漏风险 + EditorPrefs 开关
|
||
- Undo/Redo 刷新支持
|
||
|
||
**不足:**
|
||
- 外部资产变更不触发窗口刷新(N7 P2)
|
||
- DrawExitLines 用中心连线而非实际出口格坐标(N10 P2)
|
||
- OnValidate delayCall 重复追加(N2 P1)
|
||
|
||
---
|
||
|
||
### 4.5 策划友好性 — 7.5/10
|
||
|
||
**优秀:**
|
||
- 布局编辑器拖拽房间 + 冲突立即变红,无需专业编程知识
|
||
- 搜索 + 图例 + 区域着色帮助大地图快速定位
|
||
- 自动注册新房间无需手动维护 Database
|
||
- Play Mode 实时玩家位置可视化
|
||
|
||
**不足:**
|
||
- 出口连线视觉不够精确(N10),策划无法确认出口对齐
|
||
- 无键盘快捷键(如 V = 验证,F = 重置视图)
|
||
- 无批量移动/对齐多个房间能力(延续 R10-N6)
|
||
- DisplayName 无法本地化预览(延续 R10-N10)
|
||
|
||
---
|
||
|
||
### 4.6 功能完整性 — 8.5/10
|
||
|
||
**优秀:**
|
||
- 全屏地图 + 角落小地图双 UI,与头部游戏相同配置
|
||
- SetMappedBatch 支持地图碎片批量解锁
|
||
- OnRoomMapped + OnRoomMappedAnim 虚钩子,解锁动画预留
|
||
- 探索进度 API(GetExplorationProgress / ExploredRoomCount)
|
||
- MapExplorationCondition 接入成就系统
|
||
- 三种特殊房间标记(Boss / SavePoint / Shop)+ MapIconOverride 自定义
|
||
- 房间出口数据 + 过渡类型
|
||
|
||
**不足:**
|
||
- 无"全地图揭示"调试命令(开发阶段常用)
|
||
- 无地图房间分组/层级(如地下层 / 地面层分图)
|
||
- RoomOutlineTex 非矩形形状支持存在(字段已有),但编辑器无预览
|
||
|
||
---
|
||
|
||
### 4.7 鲁棒性 — 7.5/10
|
||
|
||
**优秀:**
|
||
- MapManager / MapPlayerTracker 重复实例 Awake 检测 + _isDuplicate 守门
|
||
- 全量 null 守卫(空 Database / 空房间数组)
|
||
- FormerlySerializedAs 数据兼容
|
||
- ValidateAll 四类错误检测(null / 重复 ID / 格子重叠 / 出口悬空)
|
||
- _exploredRooms / _mappedRooms 使用 HashSet 防重复
|
||
|
||
**严重不足:**
|
||
- MinimapHUD 部分订阅 Bug(N1 P1):`OnDatabaseChanged` / `OnExplorationChanged` 在特定启动顺序下永不触发
|
||
- MapPinManager.OnLoad 共享 SaveData 列表引用(N3 P1)
|
||
|
||
---
|
||
|
||
### 4.8 可扩展性 — 8.5/10
|
||
|
||
**优秀:**
|
||
- IMapService 接口易于 Mock/测试替换
|
||
- SetMappedBatch + OnRoomMapped 为地图碎片系统提供一流扩展点
|
||
- protected virtual OnRoomMappedAnim 供 UI 子类实现动画
|
||
- RoomExitData.PreferredTransitionType 枚举为未来过渡系统预留
|
||
- MapServiceExtensions 扩展方法模式
|
||
- IsDefault 标志 + AutoRegister 支持多 Database 项目
|
||
|
||
**不足:**
|
||
- 无 `IMapService.GetAllMappedRooms()` / `GetAllExploredRooms()` 返回快照 API(存档分析/成就系统需多次 HashSet 枚举)
|
||
- MapRoomDataSO 无版本号字段(热更/DLC 房间 ID 变更无法追踪遗留数据)
|
||
|
||
---
|
||
|
||
## 第 5 章:优先级修复清单
|
||
|
||
### P1 — 必须修复(影响正确性)
|
||
|
||
| 编号 | 位置 | 问题摘要 | 预估工时 |
|
||
|---|---|---|---|
|
||
| R11-N1 | `MinimapHUD.SubscribeServices` | `_subscribed` 阻止部分订阅后续补全 → mapSvc 事件永不触发 | 1h |
|
||
| R11-N2 | `MapRoomDataSO.OnValidate` | `delayCall +=` 重复追加 → 批量编辑时 N×FindAssets 卡顿 | 0.5h |
|
||
| R11-N3 | `MapPinManager.OnLoad` | 直接赋值反序列化 List → 引用共享污染 SaveData | 0.5h |
|
||
| R11-N4 | `MapPanel.CenterOnCurrentRoom` | `ForceRebuildLayoutImmediate(content)` → 大房间数时 OnEnable 卡顿 | 1h |
|
||
|
||
### P2 — 应当修复(影响体验/维护)
|
||
|
||
| 编号 | 位置 | 问题摘要 |
|
||
|---|---|---|
|
||
| R11-N5 | `MinimapHUD.RefreshView` | MapRoomCellUI 无对象池,跨房间 GC 抖动 |
|
||
| R11-N6 | `MapManager.GetRoomsByRegion` | LINQ ToArray() 无缓存 |
|
||
| R11-N7 | `MapLayoutEditorWindow` | 外部资产变更不触发 Repaint |
|
||
| R11-N8 | `MapRoomCellUI.Setup` | `pixelsPerCell` 参数对 MinimapHUD 路径无意义,API 歧义 |
|
||
| R11-N9 | `MapPlayerTracker` | 无 WorldOriginOffset,世界坐标偏移场景无法使用 |
|
||
| R11-N10 | `MapLayoutEditorWindow.DrawExitLines` | 中心连线而非出口格坐标,视觉精度低 |
|
||
| R11-N11 | `MapRoomDataSO.OnValidate` + `ValidateAll` | RoomId 无命名规则检查(Trim / 空格 / 特殊字符) |
|
||
|
||
### P3 — 可选优化
|
||
|
||
| 编号 | 问题摘要 |
|
||
|---|---|
|
||
| R11-N12 | `DrawLine` GUI.matrix 未在异常路径下恢复 |
|
||
|
||
---
|
||
|
||
## 第 6 章:与标杆游戏对比
|
||
|
||
| 特性 | 本系统 | 业界标杆 |
|
||
|---|---|---|
|
||
| 三级可见性 | ✅ Unknown / Explored / Mapped | ✅ 标准配置 |
|
||
| 角落小地图 | ✅ 视野半径可配置,增量刷新 | ✅ |
|
||
| 全屏地图 + ScrollRect 居中 | ✅ | ✅ |
|
||
| 地图碎片批量解锁 | ✅ SetMappedBatch | ✅(商店购买/触碰标牌解锁) |
|
||
| 地图标记(Pin)系统 | ✅ 多类型 + 存档 | ✅ |
|
||
| 非矩形房间形状 | ⚠️ 字段预留,编辑器无预览 | ✅(精细多边形遮罩) |
|
||
| 多区域地图(分图) | ❌ | ✅(地下/地表/秘境分区) |
|
||
| 房间Tooltip/命名 | ✅ DisplayName | ✅(带区域名动画) |
|
||
| 键盘导航地图 | ✅(WASD/方向键) | ✅ |
|
||
| 出口连接可视化 | ⚠️ 编辑器中心连线,运行时无连线 | ✅(点状通道指示) |
|
||
| 地图缩放(运行时) | ✅ 滚轮缩放 | ✅ |
|
||
| 地图揭示动画 | ⚠️ 钩子已预留,动画未实现 | ✅(逐格展开) |
|
||
|
||
---
|
||
|
||
## 第 7 章:总结
|
||
|
||
本系统在 R10 修复落地后已达到**商业级银河恶魔城地图系统的主体功能**,架构理念(接口 + ServiceLocator + 事件分离 + 脏标志)、编辑器工具套件(三窗口协同 + 自动注册)处于同类独立游戏工具的**前列水平**。
|
||
|
||
本轮发现的最高优先级问题集中在**鲁棒性细节**(MinimapHUD 部分订阅 Bug、OnValidate delayCall 堆积)和**API 设计细节**(Setup 参数歧义、GetRoomsByRegion 分配),修复这些问题后综合评分预估可恢复至 **90~91 / 100(A-)**。
|
||
|
||
长期来看,补齐以下能力可冲击 95/100(A):
|
||
1. MapRoomCellUI 对象池(N5)
|
||
2. 多区域/分图支持
|
||
3. 非矩形房间轮廓编辑器预览
|
||
4. 出口精确连线可视化(N10)
|
||
5. WorldOriginOffset 参数(N9)
|
||
|
||
---
|
||
|
||
*本报告独立于前序轮次评审,基于 2026-05-25 当前代码库完整重读后生成。*
|