- Home /
Cannot close/unload a scene that is open in editor during playmode (using C# code)?
Basically I want to open a scene whenever the user is in the editor, and then close that scene whenever the user is in playmode. Opening the scene works by using:
EditorSceneManager.OpenScene("Assets/Scenes/scenename.unity", OpenSceneMode.Additive);
However, it seems impossible to unload/close the scene whenever the user presses play. Currently I can listen to the user pressing play through:
EditorApplication.hierarchyWindowChanged
And:
EditorApplication.isPlayingOrWillChangePlaymode
I tried using the following calls to unload/close the scene before the game starts, but none of them works:
UnityEngine.SceneManagement.SceneManager.UnloadScene(scenename);
UnityEngine.SceneManagement.SceneManager.UnloadScene("Assets/Scenes/scenename.unity");
Scene s = EditorSceneManager.GetSceneByName(scenename);
EditorSceneManager.CloseScene(s, true);
To me it seems as if the SceneManagement in Unity is completeley broken, but maybe I'm just missing something? Any ideas/tips/help?
Answer by Alexander-Fedoseev · Oct 11, 2018 at 11:02 AM
Just add this script anywhere in your Assets folder (not inside Editor folder) and it will making what you want. No need to add it to gameobject as a component.
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
[InitializeOnLoadAttribute]
// Unload scenes except active scene before Play Mode
// Load them back when enter Editor Mode
public static class EditorScenes
{
static EditorScenes()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
private static void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredEditMode) OpenScenes();
if (state == PlayModeStateChange.ExitingEditMode) CloseScenes();
}
// -----------------------------------------------------
private static void OpenScenes()
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (!IsActiveScene(scene)) OpenScene(scene);
}
}
private static void CloseScenes()
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (!IsActiveScene(scene)) CloseScene(scene);
}
}
// -----------------------------------------------------
private static void OpenScene(Scene scene)
{
EditorSceneManager.OpenScene(scene.path, OpenSceneMode.Additive);
}
private static void CloseScene(Scene scene)
{
EditorSceneManager.CloseScene(scene, false);
}
// -----------------------------------------------------
private static Scene activeScene
{
get { return SceneManager.GetActiveScene(); }
}
private static bool IsActiveScene(Scene scene)
{
return scene == activeScene;
}
}
This works great for me. I slightly modified it to keep a specific named scene open while closing all the rest since I have a "title" scene that initializes a bunch of important game objects the other scenes rely on. Thanks!
Important: As this script uses the UnityEditor namespace (which isn't included in game builds), you actually NEED to add this script inside an Editor folder, or Editor assembly (if you are using asmdefs), or else the game builds will always fail. After making that adjustment, this script worked perfectly! Thanks!
Answer by TruffelsAndOranges · Jan 28, 2016 at 07:35 PM
Very interestingly those code lines work when the game IS running:
Scene s = EditorSceneManager.GetSceneByName(scenename);
EditorSceneManager.CloseScene(s, true);
But I want to close the scene BEFORE the game starts. So it's kind of broken right now since there doesn't seem to be a way to do that.
Answer by kblood · Mar 13, 2017 at 12:28 AM
This is annoying, that is sure, but its not exactly broken though, is it @TruffelsAndOranges?
You can right click each scene you have opened in the editor and unload them manually, before you actually hit play. Its meant to make it easier to work with multiple scenes in the editor, but right now, if you play while they are loaded and you have a system that loads these scenes then they will be loaded double.
I think there could be some different workarounds though. One would be to not load these scenes if you are in the editor, in the scripts. Like this:
#if !UNITY_EDITOR
Load("Player&UI");
Load("Scene2");
Load("Scene2.1");
#endif
This will make sure that you do not load these scenes if you are in the editor. But then you have to make sure that you have loaded these scenes in the editor, and that you do not unload them, or at least if you unload them, then load them again before you hit play.
Those loads use the regular SceneManager. Another way to unload all the scenes is you can do a:
// Check if in editor and do this
#if !UNITY_EDITOR
SceneManager.UnloadSceneAsync("insert scene name");
SceneManager.UnloadSceneAsync("insert scene name");
SceneManager.UnloadSceneAsync("insert scene name");
#endif
That will unload all these scenes, and you can put this in an awake command, but I am guessing that will not be good enough for you because you need these scenes to not load in the first place, and this would then be too late? I have a similar problem, and my only solution seems to be to just unload all the scenes that I have open in the editor except the scene manager scene that loads all the other scenes. They will still be in the editor though, they just become grayed out., and you can load them again after running the test by right clicking them in the hierarchy view and load them. They will only stop being in the hierarchy view if you remove them with that right right click menu.
EDIT: Hmmm... not sure here. Seems like you cannot unload the.
Well, I have played around with this some more. The scenes just cannot be found on Awake because they are all still loading. So you can unload them after the updates begin. I made a lot of things that are in "#if UNITY_EDITOR" making a variable that is told what the Time.time is during Awake, and then in update I look for a time between 0.2f after awake and 2f after awake, and redo all the scene loading and variables and such.
Pretty annoying... I guess it is still easier to just select the levels in the editor and unload them before you hit play.