Files
zeling_v2/Assets/_Game/Scripts/Editor/Scene/PersistentSceneAutoLoader.cs
Joywayer 82ce9ff09a refactor(editor): reorganize Editor directory and unify menu hierarchy
File directory changes (mirror Scripts/ module structure):
- AbilityTypeDrawer.cs         → Equipment/
- CharacterWizardWindow.cs     → Character/
- FormEditorWindow.cs          → Player/
- GMToolWindow.cs              → Tools/
- SOManagerWindow.cs           → Tools/
- Map/MapRoomDataEditor.cs     → World/Map/
- Navigation/ (root)           → Enemies/Navigation/
- Achievements/                → Progression/

Menu hierarchy changes (BaseGames/ top-level):
- Data/: +Character Wizard (from Tools/), +Boss Skill Sequence (from Tools/)
- Addressables/: +Addressable Batch Tool, +Asset Reference Graph, +Validate Address Keys (from Tools/Verification/)
- Scene/Setup/: +Boot Flow Wizard, +Scaffold *, +Auto-Open Persistent (from Tools/)
- Scene/: +Camera Area Setup (from Camera/), +Bake All NavSurfaces (from Tools/)
- Events/: +Event Bus Monitor, +Event Chain Viewer, +Create/Reimport Event Channels (from Tools/)
- Tools/Validation/: +Validate All SOs, +Apply/Validate Script Order (from Tools/ flat)
- Tools/Maintenance/: +Missing Scripts/*, +Physics2D Layer Matrix/* (from Tools/ flat)

Result: BaseGames/Tools/ reduced from 16 flat items to 4 items + 2 submenus

Docs: update AssetFolderSpec §12 editor tool table with new menu paths

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 11:52:17 +08:00

110 lines
5.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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的保证由 GameBootstrapRuntime 程序集)负责,
/// 本脚本与 Play Mode 状态无关,不监听 playModeStateChanged。
///
/// 菜单BaseGames/Scene/Setup/Auto-Open Persistent Scene
/// </summary>
[InitializeOnLoad]
public static class PersistentSceneAutoLoader
{
// ── 常量 ─────────────────────────────────────────────────────────────
private const string MenuPath = "BaseGames/Scene/Setup/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;
}
}
}