158 lines
6.0 KiB
C#
158 lines
6.0 KiB
C#
|
|
// ===============================================================================
|
||
|
|
// SmartBootstrapper - Auto-Boot Scene Loader for Unity
|
||
|
|
//
|
||
|
|
// Creator: Scove
|
||
|
|
// Last Updated: 2026-03-03
|
||
|
|
// Version: 3.0 (Drag & Drop UI Added)
|
||
|
|
//
|
||
|
|
// Purpose:
|
||
|
|
// Forces the Unity Editor to always start from an initialization (Boot) scene
|
||
|
|
// when hitting Play, regardless of which scene is currently open.
|
||
|
|
//
|
||
|
|
// Key Features:
|
||
|
|
// 1. Drag & Drop UI: Easily assign your Boot Scene via a settings window.
|
||
|
|
// 2. Persistent Settings: Saves your configuration automatically via EditorPrefs.
|
||
|
|
// 3. Quick Toggle: Enable or disable the feature directly from the window.
|
||
|
|
// 4. Smart Play Mode: Gracefully returns to your working scene after testing.
|
||
|
|
//
|
||
|
|
// How to Use:
|
||
|
|
// 1. Place this script in an 'Editor' folder.
|
||
|
|
// 2. Open via: Menu -> Tools -> Smart Boot Settings.
|
||
|
|
// 3. Drag and drop your Boot Scene into the slot and enable the tool.
|
||
|
|
// ===============================================================================
|
||
|
|
|
||
|
|
using System.IO;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEditor.SceneManagement;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
namespace Editor
|
||
|
|
{[InitializeOnLoad]
|
||
|
|
public class SmartBootstrapper : EditorWindow
|
||
|
|
{
|
||
|
|
// EditorPrefs Keys
|
||
|
|
private const string PREFS_TOGGLE_KEY = "SmartBoot_Enabled";
|
||
|
|
private const string PREFS_PATH_KEY = "SmartBoot_ScenePath";
|
||
|
|
|
||
|
|
private static bool IsEnabled
|
||
|
|
{
|
||
|
|
get => EditorPrefs.GetBool(PREFS_TOGGLE_KEY, false);
|
||
|
|
set => EditorPrefs.SetBool(PREFS_TOGGLE_KEY, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string BootScenePath
|
||
|
|
{
|
||
|
|
get => EditorPrefs.GetString(PREFS_PATH_KEY, "");
|
||
|
|
set => EditorPrefs.SetString(PREFS_PATH_KEY, value);
|
||
|
|
}[MenuItem("Tools/Smart Boot Settings")]
|
||
|
|
public static void ShowWindow()
|
||
|
|
{
|
||
|
|
SmartBootstrapper window = GetWindow<SmartBootstrapper>("Smart Boot");
|
||
|
|
window.minSize = new Vector2(350, 150);
|
||
|
|
window.maxSize = new Vector2(500, 160);
|
||
|
|
window.Show();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnGUI()
|
||
|
|
{
|
||
|
|
GUILayout.Space(10);
|
||
|
|
EditorGUILayout.LabelField("Boot Scene Configuration", EditorStyles.boldLabel);
|
||
|
|
GUILayout.Space(5);
|
||
|
|
|
||
|
|
SceneAsset currentScene = null;
|
||
|
|
if (!string.IsNullOrEmpty(BootScenePath))
|
||
|
|
{
|
||
|
|
currentScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(BootScenePath);
|
||
|
|
}
|
||
|
|
|
||
|
|
EditorGUI.BeginChangeCheck();
|
||
|
|
SceneAsset draggedScene = (SceneAsset)EditorGUILayout.ObjectField(
|
||
|
|
"Boot Scene",
|
||
|
|
currentScene,
|
||
|
|
typeof(SceneAsset),
|
||
|
|
false
|
||
|
|
);
|
||
|
|
|
||
|
|
// IF THE USER DRAGS AND DROPS A NEW SCENE
|
||
|
|
if (EditorGUI.EndChangeCheck())
|
||
|
|
{
|
||
|
|
if (draggedScene == null)
|
||
|
|
{
|
||
|
|
BootScenePath = "";
|
||
|
|
EditorSceneManager.playModeStartScene = null; // Clear immediately
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
BootScenePath = AssetDatabase.GetAssetPath(draggedScene);
|
||
|
|
EditorSceneManager.playModeStartScene = draggedScene; // Update immediately
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
GUILayout.Space(10);
|
||
|
|
|
||
|
|
EditorGUI.BeginChangeCheck();
|
||
|
|
bool newToggleState = EditorGUILayout.Toggle("Enable Auto-Boot", IsEnabled);
|
||
|
|
|
||
|
|
// IF THE USER TOGGLES THE SWITCH
|
||
|
|
if (EditorGUI.EndChangeCheck())
|
||
|
|
{
|
||
|
|
IsEnabled = newToggleState;
|
||
|
|
if (!IsEnabled)
|
||
|
|
EditorSceneManager.playModeStartScene = null; // Clear cache immediately when disabled
|
||
|
|
}
|
||
|
|
|
||
|
|
GUILayout.Space(15);
|
||
|
|
if (string.IsNullOrEmpty(BootScenePath))
|
||
|
|
{
|
||
|
|
EditorGUILayout.HelpBox("Please drag and drop a Boot Scene into the slot above.", MessageType.Warning);
|
||
|
|
}
|
||
|
|
else if (IsEnabled)
|
||
|
|
{
|
||
|
|
EditorGUILayout.HelpBox($"Ready! Hitting PLAY will always start from:\n{Path.GetFileName(BootScenePath)}", MessageType.Info);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EditorGUILayout.HelpBox("Auto-Boot is currently disabled. The active scene will play normally.", MessageType.None);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static SmartBootstrapper()
|
||
|
|
{
|
||
|
|
// Avoid registering the event multiple times on recompile
|
||
|
|
EditorApplication.playModeStateChanged -= OnPlayModeChanged;
|
||
|
|
EditorApplication.playModeStateChanged += OnPlayModeChanged;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void OnPlayModeChanged(PlayModeStateChange state)
|
||
|
|
{
|
||
|
|
if (state != PlayModeStateChange.ExitingEditMode) return;
|
||
|
|
|
||
|
|
// 1. Feature disabled or no scene assigned
|
||
|
|
if (!IsEnabled || string.IsNullOrEmpty(BootScenePath))
|
||
|
|
{
|
||
|
|
EditorSceneManager.playModeStartScene = null;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. Find Scene Asset
|
||
|
|
SceneAsset bootScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(BootScenePath);
|
||
|
|
if (bootScene == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"<b>[SmartBoot]</b> Scene not found at saved path: <color=yellow>{BootScenePath}</color>. Please re-assign it.");
|
||
|
|
EditorSceneManager.playModeStartScene = null;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. ALWAYS override with the Boot Scene (fixes old Scene sticking)
|
||
|
|
EditorSceneManager.playModeStartScene = bootScene;
|
||
|
|
|
||
|
|
// 4. Only show Log if the open Scene is not the Boot Scene
|
||
|
|
string activeScenePath = EditorSceneManager.GetActiveScene().path;
|
||
|
|
if (activeScenePath != BootScenePath)
|
||
|
|
{
|
||
|
|
string currentSceneName = Path.GetFileNameWithoutExtension(activeScenePath);
|
||
|
|
Debug.Log($"<color=#00FF00><b>[SmartBoot]</b></color> Starting from Boot Scene... <i>(Will return context to {currentSceneName})</i>");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|