Files
zeling_v2/Docs/Review/Minimap_Review_Round11_Independent.md
Joywayer f74d7f1877 Add independent review reports for Minimap system (Rounds 8, 9, and 26)
- 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.
2026-05-25 23:15:12 +08:00

472 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 小地图系统 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.3Pin 池 + Cell 保留落地) |
| 编辑器扩展 | 8.0 | ↑0.5拖拽冲突可视化、IsDefault |
| 策划友好性 | 7.5 | ↑0仍缺 DisplayName 本地化) |
| 功能完整性 | 8.5 | ↑0稳定 |
| 鲁棒性 | 7.5 | ↓0.5(发现 N11 部分订阅 Bug |
| 可扩展性 | 8.5 | ↑0.3SetMappedBatch、OnRoomMapped |
**加权综合得分85.6 / 100B+**
> R10 修复整体质量优秀;本轮发现 N1 MinimapHUD 部分订阅 BugP1 级别真实缺陷),导致鲁棒性维度扣分,综合分低于 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` 标志存在部分订阅 BugN1 P1
- MapPanel 仍通过 `StringEventChannelSO _onMapUpdated` 双通道接收单房间更新OnMapUpdated + OnExplorationChanged 语义重叠但各有其用,轻微冗余)
---
### 4.2 数据设计 — 8.5/10
**优秀:**
- 三级可见性Unknown / Explored / Mapped精确匹配银河恶魔城标准
- MapDatabaseSO 懒构建双索引id → datacell → 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 + MinimapHUDClearPins = SetActive(false) 而非 Destroy
- 脏标志驱动 UIdatabaseDirty / explorationDirty / viewDirty
- LateUpdate 双重脏检查PinsVersion + 玩家位置)
- MapDatabaseSO 空间索引 O(1) 哈希查找
**不足:**
- MinimapHUD MapRoomCellUI 无对象池N5 P2跨房间边界 GC 抖动
- CenterOnCurrentRoom 对 content ForceRebuildLayoutImmediateN4 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 虚钩子,解锁动画预留
- 探索进度 APIGetExplorationProgress / 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 部分订阅 BugN1 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 / 100A-**
长期来看,补齐以下能力可冲击 95/100A
1. MapRoomCellUI 对象池N5
2. 多区域/分图支持
3. 非矩形房间轮廓编辑器预览
4. 出口精确连线可视化N10
5. WorldOriginOffset 参数N9
---
*本报告独立于前序轮次评审,基于 2026-05-25 当前代码库完整重读后生成。*