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:
@@ -12,6 +12,8 @@ using BaseGames.UI.MainMenu;
|
||||
using BaseGames.UI.Menus;
|
||||
using BaseGames.UI.Splash;
|
||||
using BaseGames.World;
|
||||
using BaseGames.World.Map;
|
||||
using BaseGames.World.Streaming;
|
||||
using PathBerserker2d;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEditor;
|
||||
@@ -230,6 +232,9 @@ namespace BaseGames.Editor
|
||||
|
||||
AddScaffoldNote(hudRootGo, "HUDController 已挂载。其内部图片/文本/图标 Prefab 依赖较多,需后续手工补 UI 资源与事件频道。", report);
|
||||
|
||||
// ── 流式加载系统 ──────────────────────────────────────────────────
|
||||
ScaffoldStreamingSystem(services, report);
|
||||
|
||||
MarkDirtyAndLog("Persistent 场景脚手架", root, report);
|
||||
}
|
||||
|
||||
@@ -392,6 +397,79 @@ namespace BaseGames.Editor
|
||||
MarkDirtyAndLog("Game Room 脚手架", root, report);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// 流式加载系统(RoomStreamingManager + TransitionDirector)
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// 在 [Services] 下创建或更新 SYS_RoomStreamingManager,
|
||||
/// 挂载 <see cref="RoomStreamingManager"/> 与 <see cref="TransitionDirector"/>,
|
||||
/// 并自动绑定已存在的事件频道与配置资产。
|
||||
/// </summary>
|
||||
private static void ScaffoldStreamingSystem(Transform services, List<string> report)
|
||||
{
|
||||
// 预算配置 SO(不存在时自动创建)
|
||||
StreamingBudgetConfigSO budgetConfig = EnsureStreamingBudgetConfigAsset(report);
|
||||
|
||||
// MapDatabaseSO(查找已存在的资产)
|
||||
Object mapDbAsset = FindFirstAssetByType<MapDatabaseSO>("MapDatabase", "MAP_Database", "MapDatabaseSO");
|
||||
if (mapDbAsset == null)
|
||||
report.Add("未找到 MapDatabaseSO 资产。请将 MapDatabaseSO 手工赋给 RoomStreamingManager._mapDatabase 与 TransitionDirector._mapDatabase。");
|
||||
|
||||
// ── SYS_RoomStreamingManager GameObject ──────────────────────────
|
||||
GameObject streamingGo = GetOrCreateChild(services, "SYS_RoomStreamingManager").gameObject;
|
||||
|
||||
RoomStreamingManager streamingMgr = GetOrAddComponent<RoomStreamingManager>(streamingGo);
|
||||
TransitionDirector transitionDir = GetOrAddComponent<TransitionDirector>(streamingGo);
|
||||
|
||||
// ── RoomStreamingManager 字段 ─────────────────────────────────────
|
||||
AssignReference(streamingMgr, "_mapDatabase", mapDbAsset);
|
||||
AssignReference(streamingMgr, "_budget", budgetConfig);
|
||||
AssignAsset(streamingMgr, "_onRoomEntered", report, false, "EVT_RoomEntered");
|
||||
AssignAsset(streamingMgr, "_onRoomPreloaded", report, false, "EVT_RoomPreloaded");
|
||||
|
||||
// ── TransitionDirector 字段 ───────────────────────────────────────
|
||||
AssignReference(transitionDir, "_streamingManager", streamingMgr);
|
||||
AssignReference(transitionDir, "_mapDatabase", mapDbAsset);
|
||||
AssignReference(transitionDir, "_budget", budgetConfig);
|
||||
AssignAsset(transitionDir, "_onFadeOutRequest", report, false, "EVT_FadeOutRequest");
|
||||
AssignAsset(transitionDir, "_onFadeInRequest", report, false, "EVT_FadeInRequest");
|
||||
AssignAsset(transitionDir, "_onRegionNameDisplay", report, false, "EVT_RegionNameDisplay");
|
||||
AssignAsset(transitionDir, "_onSceneWorldStateRestored", report, false, "EVT_SceneWorldStateRestored");
|
||||
|
||||
report.Add("SYS_RoomStreamingManager:流式加载系统已创建。如 EVT_RoomEntered / EVT_RoomPreloaded 频道尚未存在,请通过 DataHub > Streaming 创建后重新运行脚手架。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在 <c>Assets/_Game/Data/Streaming/</c> 下确保默认预算配置 SO 存在。
|
||||
/// 已存在时直接返回;不存在时自动创建 <c>STR_BudgetConfig_Default.asset</c>。
|
||||
/// </summary>
|
||||
private static StreamingBudgetConfigSO EnsureStreamingBudgetConfigAsset(List<string> report)
|
||||
{
|
||||
// 先查找已有资产
|
||||
string[] guids = AssetDatabase.FindAssets("t:StreamingBudgetConfigSO");
|
||||
if (guids != null && guids.Length > 0)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
var existing = AssetDatabase.LoadAssetAtPath<StreamingBudgetConfigSO>(path);
|
||||
if (existing != null)
|
||||
return existing;
|
||||
}
|
||||
|
||||
// 没有则创建默认资产
|
||||
const string folder = "Assets/_Game/Data/Streaming";
|
||||
const string assetPath = folder + "/STR_BudgetConfig_Default.asset";
|
||||
EnsureFolder(folder);
|
||||
|
||||
var created = ScriptableObject.CreateInstance<StreamingBudgetConfigSO>();
|
||||
AssetDatabase.CreateAsset(created, assetPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
report.Add($"已自动创建流式加载预算配置:{assetPath}。可在 DataHub > 流式加载 中编辑默认参数。");
|
||||
return created;
|
||||
}
|
||||
|
||||
private static void AssignString(Object target, string propertyName, string value, List<string> report = null)
|
||||
{
|
||||
SerializedObject serializedObject = new SerializedObject(target);
|
||||
|
||||
Reference in New Issue
Block a user