摄像机区域的优化

This commit is contained in:
2026-05-17 07:56:12 +08:00
parent f264329751
commit d25f237e76
62 changed files with 25774 additions and 5450 deletions

View File

@@ -0,0 +1,109 @@
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/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;
}
}
}