Add independent review report for Minimap system Round 7

- Validate fixes from Round 6 and identify new issues
- Document findings including UX defects, editor integration flaws, and code quality concerns
- Propose solutions and prioritize issues based on severity
- Evaluate against standards of mature 2D Metroidvania games
This commit is contained in:
2026-05-25 14:44:31 +08:00
parent 5cb6c2a19d
commit e2bc324905
17 changed files with 1060 additions and 17 deletions

View File

@@ -42,6 +42,11 @@ namespace BaseGames.World.Map
// 复用 List 避免 RefreshView 每次分配临时 ListGC 友好)
private readonly List<string> _toRemove = new List<string>(8);
// 空间索引:格子坐标 → 房间 ID将 RefreshView step② 的 O(N) 遍历降至 O(viewRadius²)
private Dictionary<Vector2Int, string> _spatialIndex;
// 复用 HashSet 避免 RefreshView 每次分配GC 友好)
private readonly HashSet<string> _roomsInViewBuffer = new HashSet<string>(32);
private Vector2Int _currentCenter;
private string _lastDotRoomId;
private Vector2 _lastDotNormPos;
@@ -53,6 +58,8 @@ namespace BaseGames.World.Map
_mapSvc = ServiceLocator.GetOrDefault<IMapService>();
_playerProvider = ServiceLocator.GetOrDefault<IPlayerPositionProvider>();
BuildSpatialIndex(_mapSvc?.Database);
if (_playerProvider != null)
_playerProvider.OnRoomChanged += OnRoomChanged;
@@ -72,6 +79,7 @@ namespace BaseGames.World.Map
_lastDotRoomId = null;
_mapSvc = null;
_playerProvider = null;
_spatialIndex = null;
}
private void ClearAllCells()
@@ -81,6 +89,24 @@ namespace BaseGames.World.Map
_cells.Clear();
}
/// <summary>
/// 构建格子坐标 → 房间 ID 的哈希映射。
/// 将 RefreshView step② 从 O(allRooms) 全量遍历降至 O(viewRadius²) 范围格点查询。
/// 数据库变更时(如热更)应再次调用。
/// </summary>
private void BuildSpatialIndex(MapDatabaseSO db)
{
_spatialIndex = new Dictionary<Vector2Int, string>();
if (db?.AllRooms == null) return;
foreach (var room in db.AllRooms)
{
if (room == null) continue;
for (int x = 0; x < room.GridSize.x; x++)
for (int y = 0; y < room.GridSize.y; y++)
_spatialIndex[new Vector2Int(room.GridPosition.x + x, room.GridPosition.y + y)] = room.RoomId;
}
}
private void LateUpdate()
{
UpdatePlayerDot();
@@ -133,16 +159,30 @@ namespace BaseGames.World.Map
}
foreach (var id in _toRemove) _cells.Remove(id);
// ② 实例化新进入范围的格子
foreach (var room in db.AllRooms)
// ② 用空间索引替代 O(N) 全量遍历,在可视范围格点上查询所属房间
// 复杂度O(viewRadius²) 替代 O(allRooms),大地图下效果显著
_roomsInViewBuffer.Clear();
if (_spatialIndex != null)
{
if (room == null || _cells.ContainsKey(room.RoomId)) continue;
if (!RoomInView(room, minX, maxX, minY, maxY)) continue;
for (int x = minX; x <= maxX; x++)
for (int y = minY; y <= maxY; y++)
{
if (_spatialIndex.TryGetValue(new Vector2Int(x, y), out var rId))
_roomsInViewBuffer.Add(rId);
}
}
foreach (var roomId in _roomsInViewBuffer)
{
if (_cells.ContainsKey(roomId)) continue;
var room = db.GetRoom(roomId);
if (room == null) continue;
var cell = Instantiate(_cellPrefab, _cellContainer);
cell.Setup(room, _mapSvc.GetVisibility(room.RoomId), null);
cell.SetColors(_colorExplored, _colorMapped, _colorUnknown);
_cells[room.RoomId] = cell;
PlaceCell(cell, room); // 立即设置正确的中心相对坐标,避免 Setup 默认偏移被 step③ 覆盖
_cells[roomId] = cell;
}
// ③ 重定位所有格子(中心发生变化时)