- 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.
143 lines
7.3 KiB
Markdown
143 lines
7.3 KiB
Markdown
# 小地图系统独立评审 — 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<IMapService>(); // 每次 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 层职责,在本模块范围外)。
|