feat: Implement Room Streaming System

- Add RoomStreamingManager to manage room loading and unloading based on player proximity.
- Create StreamingBudgetConfigSO for memory and performance budgeting of the streaming system.
- Introduce TransitionDirector to handle seamless and atmospheric fade transitions between rooms.
- Develop WorldGraph to represent room connectivity and facilitate neighbor queries and distance calculations.
- Implement RoomNode and RoomEdge classes to structure room data and connections.
This commit is contained in:
2026-05-23 19:10:29 +08:00
parent 81c326af53
commit a1b4e629aa
165 changed files with 7904 additions and 313 deletions

View File

@@ -6,11 +6,15 @@ namespace BaseGames.World
{
/// <summary>
/// 房间控制器。挂在每个房间场景的 [RoomRoot] 下。
/// Start 时切换摄像机到玩家当前所在的 CameraArea并提供出生点查询。
/// <para>
/// 在流式加载模式下(<see cref="IRoomStreamingManager"/> 已注册Start() 将自身注册到
/// 流式管理器,由管理器控制相机初始化时机,避免 Dormant 房间抢占相机。
/// 非流式模式(无管理器注册)则退回原有行为,在 Start() 中立即初始化相机。
/// </para>
/// 支持房间内存在多个 CameraArea 的情况:动态检测玩家位于哪个触发区域,
/// 无匹配时回退到场景内第一个 CameraArea。
/// </summary>
public class RoomController : MonoBehaviour
public class RoomController : MonoBehaviour, IRoomLifecycle
{
[SerializeField] private string _roomId;
[SerializeField] private PlayerSpawnPoint[] _spawnPoints;
@@ -23,6 +27,39 @@ namespace BaseGames.World
public string RoomId => _roomId;
private void Start()
{
// 流式模式:注册到管理器,由管理器控制相机初始化时机(避免 Dormant 房间抢占相机)
var streaming = ServiceLocator.GetOrDefault<IRoomStreamingManager>();
if (streaming != null)
{
streaming.RegisterRoomController(this);
return;
}
// 非流式模式(管理器未注册):立即初始化相机,保持原有行为
SetupCamera();
}
// ── IRoomLifecycle ────────────────────────────────────────────────────────
/// <summary>
/// 房间进入休眠时由 <see cref="Streaming.RoomHandle"/> 调用。
/// 相机无需额外操作,视觉隐藏由 RoomHandle 批量关闭 Renderer 完成。
/// </summary>
public void OnRoomDormant() { }
/// <summary>
/// 房间被激活时由 <see cref="Streaming.RoomHandle"/> 调用,重新初始化相机区域。
/// </summary>
public void OnRoomActivate(SpawnContext context)
{
SetupCamera();
}
// ── 相机初始化 ────────────────────────────────────────────────────────────
/// <summary>初始化相机区域。可由 Start() 或 OnRoomActivate() 调用。</summary>
public void SetupCamera()
{
// 显式覆盖优先:直接使用编辑器/工具指定的基线区域
CameraArea area = _cameraArea != null ? _cameraArea : FindAreaForPlayer();