Skip to content

Instantly share code, notes, and snippets.

@shane-harper
Last active June 4, 2019 12:39
Show Gist options
  • Save shane-harper/9d3703241a50c465bead31b7f8595397 to your computer and use it in GitHub Desktop.
Save shane-harper/9d3703241a50c465bead31b7f8595397 to your computer and use it in GitHub Desktop.
Auto opens a scene on Unity Editor play
using System;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
[InitializeOnLoad]
internal static class SceneAutoLoader
{
private const string MenuFolder = "Edit/Scene Auto Load/";
private const string ToggleMenuItem = MenuFolder + "Enabled";
private const string SelectSceneMenuItem = MenuFolder + "Select Scene...";
private const string PrefLoadMasterOnPlay = "SceneAutoLoader.Enabled";
private const string PrefMasterScene = "SceneAutoLoader.MasterScene";
private const string PrefPreviousScene = "SceneAutoLoader.PreviousScene";
static SceneAutoLoader()
{
// Subscribe to event if enabled
if (Enabled) EditorApplication.playModeStateChanged += OnPlayModeChanged;
// TODO this can sometimes throw an error on editor opening (harmless but ugly)
Menu.SetChecked(ToggleMenuItem, Enabled);
}
/// <summary>
/// Returns true if the tool is currently enabled
/// </summary>
private static bool Enabled
{
get { return PlayerPrefs.GetInt(PrefLoadMasterOnPlay, 0) == 1; }
set { PlayerPrefs.SetInt(PrefLoadMasterOnPlay, value ? 1 : 0); }
}
/// <summary>
/// The currently set master scene
/// </summary>
private static string MasterScene
{
get { return PlayerPrefs.GetString(PrefMasterScene, DefaultMasterScene); }
set { PlayerPrefs.SetString(PrefMasterScene, value); }
}
/// <summary>
/// Last scene the user was on before they pressed play
/// </summary>
private static string PreviousScene
{
get { return PlayerPrefs.GetString(PrefPreviousScene, SceneManager.GetActiveScene().path); }
set { PlayerPrefs.SetString(PrefPreviousScene, value); }
}
/// <summary>
/// Get path to default master scene. Used when no master scene is set
/// </summary>
private static string DefaultMasterScene
{
get { return EditorBuildSettings.scenes.Length > 0 ? EditorBuildSettings.scenes[0].path : null; }
}
[MenuItem(SelectSceneMenuItem)]
public static void SelectMasterScene()
{
var masterScene = EditorUtility.OpenFilePanel("Select Master Scene", Application.dataPath, "unity");
masterScene = masterScene.Replace(Application.dataPath, "Assets");
if (string.IsNullOrEmpty(masterScene)) return;
MasterScene = masterScene;
// Enable if disabled
if (!Enabled) Toggle();
}
[MenuItem(ToggleMenuItem)]
public static void Toggle()
{
Enabled = !Enabled;
Menu.SetChecked(ToggleMenuItem, Enabled);
if (Enabled) EditorApplication.playModeStateChanged += OnPlayModeChanged;
else EditorApplication.playModeStateChanged -= OnPlayModeChanged;
}
[MenuItem(ToggleMenuItem, true)]
private static bool ToggleCheck()
{
Menu.SetChecked(ToggleMenuItem, Enabled);
return true;
}
private static void OnPlayModeChanged(PlayModeStateChange state)
{
switch (state)
{
case PlayModeStateChange.ExitingEditMode:
{
OnPlay();
break;
}
case PlayModeStateChange.EnteredEditMode:
{
OnStop();
break;
}
}
}
private static void OnPlay()
{
// If no master scene is set, don't do anything
if (string.IsNullOrEmpty(MasterScene)) return;
// Cache previous scene path, ignore if already on the master scene
PreviousScene = SceneManager.GetActiveScene().path;
if (PreviousScene == MasterScene)
{
PreviousScene = null;
return;
}
// Show save dialog
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
// Open master scene
try
{
EditorSceneManager.OpenScene(MasterScene);
}
catch (Exception)
{
EditorApplication.isPlaying = false;
// Disable if currently enabled as current master scene selection does not exist
if (Enabled) Toggle();
}
else
// Cancel playing if user chooses to cancel the save dialog
EditorApplication.isPlaying = false;
}
private static void OnStop()
{
// Don't attempt to load previous scene if it's not set
if (string.IsNullOrEmpty(PreviousScene)) return;
try
{
// Open previous scene
EditorSceneManager.OpenScene(PreviousScene);
}
catch (Exception)
{
// Previous scene doesn't exist anymore
Debug.LogErrorFormat("Scene Auto Loader: Couldn't find previous scene to load.\n{0}", PreviousScene);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment