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

@@ -0,0 +1,71 @@
using UnityEngine;
namespace BaseGames.World.Streaming
{
/// <summary>
/// 流式加载系统的内存与性能预算配置。
/// 挂载于 Persistent 场景的 SYS_RoomStreamingManager 对象上,或通过 Inspector 注入。
/// 可为不同目标平台PC / 主机 / 移动端)准备多份配置资产。
/// 资产路径Assets/_Game/Data/Streaming/
/// </summary>
[CreateAssetMenu(menuName = "BaseGames/World/Streaming/BudgetConfig")]
public class StreamingBudgetConfigSO : ScriptableObject
{
[Header("内存与容量")]
[Tooltip("同时保持 Dormant 状态的最大房间数量(不含当前 Active 房间)。\n" +
"超出此限制后LRU 策略将卸载距离最远、最久未访问的 Dormant 房间。")]
[Min(1)]
public int MaxDormantRooms = 6;
[Tooltip("房间资产内存上限MB。仅用于超出时触发 LRU 卸载的第二道保障检查。\n" +
"需在编辑器 Profiler 中测量各房间实际内存后填入估算值。")]
[Min(64)]
public int MaxMemoryMB = 300;
[Header("加载控制")]
[Tooltip("同时进行的 Addressables 加载操作数量上限。\n" +
"过高会导致 I/O 竞争和帧率波动,建议 1-2。")]
[Range(1, 4)]
public int MaxConcurrentLoads = 2;
[Tooltip("预加载的邻居跳数。\n" +
"1 = 仅预加载直接相邻出口的房间2 = 再加载邻居的邻居。\n" +
"值越高预加载越激进,内存压力越大。")]
[Range(1, 3)]
public int PreloadLookaheadHops = 2;
[Header("激活与冷却")]
[Tooltip("玩家离开房间后,延迟多少秒才将该房间转为 Dormant/Unloaded。\n" +
"防止来回反复时频繁卸载重载。推荐 5-10 s。")]
[Min(0f)]
public float CoolingDuration = 6f;
[Tooltip("房间 Activate 时每帧最多激活的 IRoomLifecycle 数量,分帧避免 CPU 峰值。")]
[Min(1)]
public int LifecycleActivatePerFrame = 8;
[Header("AtmosphericFade 演出")]
[Tooltip("AtmosphericFade 过渡的淡出时长(秒)。")]
[Range(0.1f, 1f)]
public float AtmosphericFadeOutDuration = 0.25f;
[Tooltip("AtmosphericFade 过渡的淡入时长(秒)。")]
[Range(0.1f, 1f)]
public float AtmosphericFadeInDuration = 0.3f;
[Tooltip("AtmosphericFade 过渡中,区域名称文本显示的最短持续时间(秒)。")]
[Range(0.5f, 3f)]
public float RegionNameDisplayDuration = 1.2f;
[Header("Seamless 过渡等待")]
[Tooltip("Seamless 过渡等待目标房间预加载完成的最长时间(秒)。\n" +
"超时后放弃本次切换,玩家可再次触发(届时房间通常已就绪)。")]
[Range(2f, 30f)]
public float SeamlessWaitTimeout = 10f;
}
}