地图系统

This commit is contained in:
2026-06-05 18:41:33 +08:00
parent 613f2a4d13
commit fe4fd60083
234 changed files with 33090 additions and 4899 deletions

View File

@@ -0,0 +1,76 @@
using System.Collections.Generic;
using UnityEngine;
namespace BaseGames.World.Map
{
/// <summary>
/// 全局区域注册表 SO。
///
/// 设计原则:<see cref="MapRoomDataSO.RegionId"/> 是房间归属的单一权威来源。
/// 本 SO 持有所有 <see cref="RegionDefinitionSO"/> 资产引用,运行时从
/// <see cref="MapDatabaseSO"/> 惰性构建 SceneName → Region 缓存,
/// 消除了原 RegionDefinitionSO.roomSceneNames 与 MapRoomDataSO.RegionId 的双重冗余。
///
/// 资产路径Assets/_Game/Data/Map/RegionRegistry.asset
/// </summary>
[CreateAssetMenu(menuName = "BaseGames/Map/RegionRegistry", fileName = "RegionRegistry")]
public class RegionRegistrySO : ScriptableObject
{
[Tooltip("项目中所有 RegionDefinitionSO 资产。新增区域 SO 时同步添加到此数组。")]
[SerializeField] private RegionDefinitionSO[] _regions;
[Tooltip("地图数据库,用于从 MapRoomDataSO.RegionId 构建 SceneName → Region 缓存(单一权威来源)。")]
[SerializeField] private MapDatabaseSO _mapDatabase;
private Dictionary<string, RegionDefinitionSO> _regionById;
private Dictionary<string, RegionDefinitionSO> _sceneToRegion;
/// <summary>根据场景名MapRoomDataSO.RoomId查找所属区域未找到返回 null。</summary>
public RegionDefinitionSO FindBySceneName(string sceneName)
{
if (string.IsNullOrEmpty(sceneName)) return null;
BuildCacheIfNeeded();
_sceneToRegion.TryGetValue(sceneName, out var region);
return region;
}
/// <summary>根据 regionId 直接查找;未找到返回 null。</summary>
public RegionDefinitionSO FindById(string regionId)
{
if (string.IsNullOrEmpty(regionId)) return null;
BuildCacheIfNeeded();
_regionById.TryGetValue(regionId, out var region);
return region;
}
private void BuildCacheIfNeeded()
{
if (_sceneToRegion != null) return;
// Step 1: regionId → RegionDefinitionSO
_regionById = new Dictionary<string, RegionDefinitionSO>(System.StringComparer.OrdinalIgnoreCase);
if (_regions != null)
foreach (var r in _regions)
if (r != null && !string.IsNullOrEmpty(r.regionId))
_regionById[r.regionId] = r;
// Step 2: sceneName → RegionDefinitionSO以 MapRoomDataSO.RegionId 为权威来源
_sceneToRegion = new Dictionary<string, RegionDefinitionSO>(System.StringComparer.OrdinalIgnoreCase);
if (_mapDatabase?.AllRooms == null) return;
foreach (var room in _mapDatabase.AllRooms)
{
if (room == null || string.IsNullOrEmpty(room.RoomId) || string.IsNullOrEmpty(room.RegionId))
continue;
if (_regionById.TryGetValue(room.RegionId, out var def))
_sceneToRegion[room.RoomId] = def;
}
}
private void OnValidate()
{
_sceneToRegion = null;
_regionById = null;
}
}
}