Skip to content

Instantly share code, notes, and snippets.

@BenVella
Forked from pdcp1/SceneAutoLoader.cs
Last active February 23, 2024 22:46
Show Gist options
  • Save BenVella/cce177aee3025819a0aef729df30573f to your computer and use it in GitHub Desktop.
Save BenVella/cce177aee3025819a0aef729df30573f to your computer and use it in GitHub Desktop.
SceneAutoLoader with additive loading
using System;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Editor
{
/// <summary>
/// Scene auto loader.
/// </summary>
/// <description>
/// This class adds a File > Scene Autoload menu containing options to select
/// a "master scene" enable it to be auto-loaded when the user presses play
/// in the editor. When enabled, the selected scene will be loaded on play,
/// then the original scene will be reloaded on stop.
///
/// Based on an idea on this thread:
/// http://forum.unity3d.com/threads/157502-Executing-first-scene-in-build-settings-when-pressing-play-button-in-editor
/// </description>
[InitializeOnLoad]
internal static class SceneAutoLoader
{
// Static constructor binds a playmode-changed callback.
// [InitializeOnLoad] above makes sure this gets executed.
static SceneAutoLoader()
{
EditorApplication.playModeStateChanged += OnPlayModeChanged;
}
// Menu items to select the "master" scene and control whether or not to load it.
[MenuItem("File/Scene Autoload/Select Master Scene...")]
private static void SelectMasterScene()
{
string masterScene = EditorUtility.OpenFilePanel("Select Master Scene", Application.dataPath, "unity");
if (!string.IsNullOrEmpty(masterScene))
{
MasterScene = masterScene;
LoadMasterOnPlay = true;
}
}
[MenuItem("File/Scene Autoload/----------------------")]
private static void Separator1()
{}
[MenuItem("File/Scene Autoload/Load Master On Play", true)]
private static bool ShowLoadMasterOnPlay()
{
return !LoadMasterOnPlay;
}
[MenuItem("File/Scene Autoload/Load Master On Play")]
private static void EnableLoadMasterOnPlay()
{
LoadMasterOnPlay = true;
}
[MenuItem("File/Scene Autoload/Don't Load Master On Play", true)]
private static bool ShowDontLoadMasterOnPlay()
{
return LoadMasterOnPlay;
}
[MenuItem("File/Scene Autoload/Don't Load Master On Play")]
private static void DisableLoadMasterOnPlay()
{
LoadMasterOnPlay = false;
}
[MenuItem("File/Scene Autoload/-------------------------")]
private static void Separator2()
{ }
[MenuItem("File/Scene Autoload/Load current scene additively", true)]
private static bool ShowLoadAdditiveCurrentScene()
{
return !LoadAdditiveCurrentScene;
}
[MenuItem("File/Scene Autoload/Load current scene additively")]
private static void EnableLoadAdditiveCurrentScene()
{
LoadAdditiveCurrentScene = true;
}
[MenuItem("File/Scene Autoload/Don't Load current scene additively", true)]
private static bool ShowDontLoadAdditiveCurrentScene()
{
return LoadAdditiveCurrentScene;
}
[MenuItem("File/Scene Autoload/Don't Load current scene additively")]
private static void DisableLoadAdditiveCurrentScene()
{
LoadAdditiveCurrentScene = false;
}
// Play mode change callback handles the scene load/reload.
private static void OnPlayModeChanged(PlayModeStateChange playModeStateChange)
{
if (!LoadMasterOnPlay)
{
return;
}
switch (playModeStateChange)
{
case PlayModeStateChange.ExitingEditMode:
BeginningPlay();
break;
case PlayModeStateChange.EnteredEditMode:
StoppingPlay();
break;
case PlayModeStateChange.EnteredPlayMode:
case PlayModeStateChange.ExitingPlayMode:
default:
return;
}
}
private static void StoppingPlay()
{
try
{
EditorSceneManager.OpenScene(PreviousScene);
}
catch (ArgumentException argEx)
{
Debug.LogError($"Failed to open {PreviousScene}. Error: {argEx.Message}\n{argEx.StackTrace}");
}
}
private static void BeginningPlay()
{
PreviousScene = SceneManager.GetActiveScene().path;
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
try
{
EditorSceneManager.OpenScene(MasterScene);
}
catch (ArgumentException argEx)
{
Debug.LogError($"Failed to open {MasterScene}. Error: {argEx.Message}\n{argEx.StackTrace}");
EditorApplication.isPlaying = false;
}
}
else
{
// User cancelled the save operation -- cancel play as well.
EditorApplication.isPlaying = false;
}
if (LoadAdditiveCurrentScene)
{
var sceneName = PreviousScene.Split('/', '.');
SceneManager.LoadScene(sceneName[^2]);
}
}
// Properties are remembered as editor preferences.
private const string EditorPrefLoadMasterOnPlay = "SceneAutoLoader.LoadMasterOnPlay";
private const string EditorPrefMasterScene = "SceneAutoLoader.MasterScene";
private const string EditorPrefPreviousScene = "SceneAutoLoader.PreviousScene";
private const string EditorPrefLoadAdditiveCurrentScene = "SceneAutoLoader.LoadAdditiveCurrentScene";
private static bool LoadMasterOnPlay
{
get => EditorPrefs.GetBool(EditorPrefLoadMasterOnPlay, false);
set => EditorPrefs.SetBool(EditorPrefLoadMasterOnPlay, value);
}
private static string MasterScene
{
get => EditorPrefs.GetString(EditorPrefMasterScene, "Master.unity");
set => EditorPrefs.SetString(EditorPrefMasterScene, value);
}
private static string PreviousScene
{
get => EditorPrefs.GetString(EditorPrefPreviousScene, SceneManager.GetActiveScene().name);
set => EditorPrefs.SetString(EditorPrefPreviousScene, value);
}
private static bool LoadAdditiveCurrentScene
{
get => EditorPrefs.GetBool(EditorPrefLoadAdditiveCurrentScene, false);
set => EditorPrefs.SetBool(EditorPrefLoadAdditiveCurrentScene, value);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment