1
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AddressableAssets;
|
||||
using UnityEditor.AddressableAssets.Settings;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
/// <summary>
|
||||
/// 创建纯 AOT 引导场景 BootScene 并配置 Build Settings / Addressables。
|
||||
/// 引导场景保持全空(不挂任何组件),规避 HybridCLR "热更脚本不能挂在随主包场景上" 的限制。
|
||||
/// 启动流程:BootScene(空)→ Launcher 加载热更 dll → 通过 Addressables 加载 UIScene。
|
||||
/// </summary>
|
||||
public static class BootSceneCreator
|
||||
{
|
||||
private const string BootScenePath = "Assets/MyGame/Scenes/BootScene.unity";
|
||||
private const string UIScenePath = "Assets/MyGame/Scenes/UIScene.unity";
|
||||
|
||||
[MenuItem("Tools/Create BootScene")]
|
||||
public static void CreateBootScene()
|
||||
{
|
||||
// 1. 新建空场景
|
||||
// 引导场景必须保持“全空”:不挂任何热更 MonoBehaviour(否则构建时会被判为 missing script),
|
||||
// 也不需要挂 AOT 单例——Launcher 是 static 类,靠 RuntimeInitializeOnLoadMethod 自动执行;
|
||||
// BeijingTimeManager 是 MonoSingleton(Awake 里 DontDestroyOnLoad),它已经挂在 UIScene 上,
|
||||
// 在这里再挂一份反而会产生两个实例(两份定时同步循环)。
|
||||
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||||
|
||||
// 2. 保存场景
|
||||
bool saved = EditorSceneManager.SaveScene(scene, BootScenePath);
|
||||
if (!saved)
|
||||
{
|
||||
Debug.LogError("[BootSceneCreator] 引导场景保存失败");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[BootSceneCreator] 引导场景已创建: {BootScenePath}");
|
||||
|
||||
// 3. 更新 Build Settings:
|
||||
// - BootScene 设为第一个(启动场景)
|
||||
// - UIScene 从 Build Settings 移除(改为通过 Addressables 加载)
|
||||
// - 其他场景保留
|
||||
UpdateBuildSettings();
|
||||
|
||||
// 4. 把 UIScene 标记为 Addressable(key = "UIScene"),Launcher 会按这个 key 加载
|
||||
MarkUISceneAddressable();
|
||||
|
||||
// 5. 打开引导场景
|
||||
EditorSceneManager.OpenScene(BootScenePath);
|
||||
|
||||
Debug.Log("[BootSceneCreator] 完成!请运行 HybridCLR > Generate > All 并重新构建。");
|
||||
}
|
||||
|
||||
private static void UpdateBuildSettings()
|
||||
{
|
||||
var scenes = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes);
|
||||
|
||||
// 移除已存在的 BootScene(防重复)
|
||||
scenes.RemoveAll(s => s.path == BootScenePath);
|
||||
|
||||
// BootScene 插到最前面
|
||||
scenes.Insert(0, new EditorBuildSettingsScene(BootScenePath, true));
|
||||
|
||||
// 移除 UIScene(现在由 Addressables 加载,不再随主包)
|
||||
scenes.RemoveAll(s => s.path == UIScenePath);
|
||||
|
||||
EditorBuildSettings.scenes = scenes.ToArray();
|
||||
|
||||
Debug.Log("[BootSceneCreator] Build Settings 已更新:BootScene 为启动场景,UIScene 已移除(改走 Addressables)。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 把 UIScene 标记为 Addressable,address key 设为 "UIScene"。
|
||||
/// Launcher 会按这个 key 通过 Addressables 加载主场景。
|
||||
/// </summary>
|
||||
private static void MarkUISceneAddressable()
|
||||
{
|
||||
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
||||
if (settings == null)
|
||||
{
|
||||
Debug.LogError("[BootSceneCreator] AddressableAssetSettings 不存在,请先初始化 Addressables。");
|
||||
return;
|
||||
}
|
||||
|
||||
string uiSceneGuid = AssetDatabase.AssetPathToGUID(UIScenePath);
|
||||
if (string.IsNullOrEmpty(uiSceneGuid))
|
||||
{
|
||||
Debug.LogError($"[BootSceneCreator] 找不到 UIScene: {UIScenePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 用默认组(Default Local Group)。如果项目有专门的场景组,可手动改。
|
||||
AddressableAssetGroup group = settings.DefaultGroup;
|
||||
if (group == null)
|
||||
{
|
||||
Debug.LogError("[BootSceneCreator] Addressables 默认组不存在。");
|
||||
return;
|
||||
}
|
||||
|
||||
AddressableAssetEntry entry = settings.CreateOrMoveEntry(uiSceneGuid, group);
|
||||
entry.address = "UIScene";
|
||||
|
||||
EditorUtility.SetDirty(settings);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log($"[BootSceneCreator] UIScene 已标记为 Addressable,key='UIScene',组='{group.Name}'。");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user