77 lines
3.2 KiB
C#
77 lines
3.2 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|