110 lines
5.5 KiB
C#
110 lines
5.5 KiB
C#
using UnityEditor;
|
||
using UnityEditor.SceneManagement;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
|
||
namespace BaseGames.Editor
|
||
{
|
||
/// <summary>
|
||
/// 编辑器 Edit Mode 辅助:打开任意场景时自动将 Persistent 场景 Additive 加入 Hierarchy。
|
||
///
|
||
/// 职责范围(仅限 Edit Mode):
|
||
/// 让设计师在编辑房间场景时,Inspector 中可直接看到并配置 GameManager / SceneService
|
||
/// 等 Persistent 场景内的组件,无需手动 Open Additive。
|
||
///
|
||
/// 运行时(Play Mode / 发行版 Build)的保证由 GameBootstrap(Runtime 程序集)负责,
|
||
/// 本脚本与 Play Mode 状态无关,不监听 playModeStateChanged。
|
||
///
|
||
/// 菜单:BaseGames/Tools/Edit Mode: Auto-Open Persistent Scene
|
||
/// </summary>
|
||
[InitializeOnLoad]
|
||
public static class PersistentSceneAutoLoader
|
||
{
|
||
// ── 常量 ─────────────────────────────────────────────────────────────
|
||
private const string MenuPath = "BaseGames/Tools/Edit Mode: Auto-Open Persistent Scene";
|
||
private const string PrefKey = "BaseGames_EditAutoOpen_Persistent";
|
||
private const string PersistentSceneName = "Scene_Persistent";
|
||
|
||
// ── 构造(Editor 启动时执行)──────────────────────────────────────────
|
||
static PersistentSceneAutoLoader()
|
||
{
|
||
EditorSceneManager.sceneOpened += OnSceneOpened;
|
||
|
||
// 启动时补一次检查:Editor 已打开但 Persistent 不在 Hierarchy 的场景
|
||
EditorApplication.delayCall += EnsurePersistentInHierarchyEditMode;
|
||
}
|
||
|
||
// ── 菜单 ─────────────────────────────────────────────────────────────
|
||
[MenuItem(MenuPath, validate = false, priority = 301)]
|
||
private static void ToggleEnabled()
|
||
{
|
||
bool current = EditorPrefs.GetBool(PrefKey, true);
|
||
EditorPrefs.SetBool(PrefKey, !current);
|
||
}
|
||
|
||
[MenuItem(MenuPath, validate = true)]
|
||
private static bool ToggleEnabledValidate()
|
||
{
|
||
Menu.SetChecked(MenuPath, EditorPrefs.GetBool(PrefKey, true));
|
||
return true;
|
||
}
|
||
|
||
// ── 场景打开回调 ──────────────────────────────────────────────────────
|
||
private static void OnSceneOpened(Scene scene, OpenSceneMode mode)
|
||
{
|
||
// 若是 Persistent 本身被打开,无需额外处理
|
||
if (IsPersistentScene(scene.name)) return;
|
||
|
||
// Single 模式(替换当前场景)或 Additive 加入新场景时,确保 Persistent 也在 Hierarchy 中
|
||
// 使用 delayCall 避免在场景加载中途调用 OpenScene
|
||
EditorApplication.delayCall += EnsurePersistentInHierarchyEditMode;
|
||
}
|
||
|
||
// ── 核心逻辑 ──────────────────────────────────────────────────────────
|
||
private static void EnsurePersistentInHierarchyEditMode()
|
||
{
|
||
// 仅在 Edit Mode 执行(Play Mode 由 GameBootstrap 负责)
|
||
if (Application.isPlaying) return;
|
||
if (!EditorPrefs.GetBool(PrefKey, true)) return;
|
||
|
||
// 若 Persistent 已在 Hierarchy,无需操作
|
||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||
if (IsPersistentScene(SceneManager.GetSceneAt(i).name)) return;
|
||
|
||
// 查找并 Additive 打开 Persistent 场景
|
||
string path = FindPersistentScenePath();
|
||
if (string.IsNullOrEmpty(path))
|
||
{
|
||
Debug.LogWarning(
|
||
$"[PersistentAutoLoader] 未找到 '{PersistentSceneName}' 场景。" +
|
||
"请确认场景已添加到 Build Settings 或可在 Assets 中搜索到。");
|
||
return;
|
||
}
|
||
|
||
EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);
|
||
}
|
||
|
||
// ── 工具函数 ──────────────────────────────────────────────────────────
|
||
private static bool IsPersistentScene(string sceneName)
|
||
=> sceneName == PersistentSceneName || sceneName == "Persistent";
|
||
|
||
private static string FindPersistentScenePath()
|
||
{
|
||
// 优先从 Build Settings 查找(保证与 GameBootstrap 使用同一文件)
|
||
foreach (var buildScene in EditorBuildSettings.scenes)
|
||
{
|
||
if (!buildScene.enabled) continue;
|
||
string name = System.IO.Path.GetFileNameWithoutExtension(buildScene.path);
|
||
if (IsPersistentScene(name)) return buildScene.path;
|
||
}
|
||
|
||
// 回退:在 AssetDatabase 中搜索
|
||
string[] guids = AssetDatabase.FindAssets($"t:Scene {PersistentSceneName}");
|
||
if (guids.Length > 0) return AssetDatabase.GUIDToAssetPath(guids[0]);
|
||
|
||
guids = AssetDatabase.FindAssets("t:Scene Persistent");
|
||
return guids.Length > 0 ? AssetDatabase.GUIDToAssetPath(guids[0]) : null;
|
||
}
|
||
}
|
||
}
|