Hi, I am trying to create an editor script to help with my project development. I have organized my game into 2 scenes, one scene has some critical assets that the player needs at the very beginning, but the other scene has content that is loaded through the Addressables system later on.
I want to be able to test the entire workflow while having both scenes in the editor. I need to unload the scene with addressable content when I press the play button (it will then get loaded in naturally when the game starts playing).
I have found 3 API’s for this online, but all of them seem to be broken. I wrote this test script that outlines the 3 methods I tried.
First: EditorSceneManager.CloseScene
This doesn’t seem to do anything, no matter what parameters I pass to it.
Second: EditorSceneManager.UnloadScene
This also doesn’t do anything, and it is also marked as deprecated.
Third: EditorSceneManager.UnloadSceneAsync
This will unload the scene, but it doesn’t do it until multiple objects from the Addressable scene have finished their Awake functions, which causes errors in my game.
I tried all 3 of these functions in a static constructor with the [InitializeOnLoad] attribute and I also tried all 3 when subscribing to the EditorApplication.playModeStateChanged event and only the UnloadSceneAsync call actually unloaded the scene, but not before Awake functions were triggered.
Anyone have any experience with this sort of thing? Thanks!
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
// ensure class initializer is called whenever scripts recompile
[InitializeOnLoadAttribute]
public static class PlayModeStateChangedExample
{
// register an event handler when the class is initialized
static PlayModeStateChangedExample()
{
// Without checking this bool value, this code will be executed when the project is recompiled, so we will unload the addressables scene a lot.
if (!EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
// Get the Addressable content scene by name
var addressableScene = EditorSceneManager.GetSceneByName("Template_4kPortrait_Addressable_Content");
// Will print "scene path: Assets/Template_4kPortrait_Addressable_Content.unity" in the console
//Debug.Log("scene path: " + addressableScene.path);
// This function call does not unload the addressable scene. Passing true or false has no effect.
//bool result = EditorSceneManager.CloseScene(addressableScene, true);
// This function is deprecated. It also doesn't seem to work when called here.
//bool result = EditorSceneManager.UnloadScene(addressableScene);
// This function throws an error. System.InvalidOperationException: This can only be used during play mode, please use EditorSceneManager.CloseScene() instead.
//EditorSceneManager.UnloadSceneAsync(@"Assets/Template_4kPortrait_Addressable_Content.unity", UnloadSceneOptions.UnloadAllEmbeddedSceneObjects);
// Log for sanity.
Debug.Log("Close addressable scene");
// This event is triggered AFTER the game starts playing, so several Awake functions have already been fired.
//EditorApplication.playModeStateChanged += LogPlayModeState;
}
/// <summary>
/// This code will not run in time because it is triggered after the initial Awake functions are called on objects in the Addressables Scene
/// </summary>
/// <param name="state"></param>
private static void LogPlayModeState(PlayModeStateChange state)
{
Debug.Log(state);
// Get the Addressable content scene by name
var addressableScene = EditorSceneManager.GetSceneByName("Template_4kPortrait_Addressable_Content");
// This function call does not unload the addressable scene. Passing true or false has no effect.
//bool result = EditorSceneManager.CloseScene(addressableScene, false);
// This function is deprecated. It also doesn't work.
//bool result = EditorSceneManager.UnloadScene(addressableScene);
// This call works, but by the time it is finished, we will already have errors from multiple objects Awake calls being triggered and initializing things with the wrong object
//EditorSceneManager.UnloadSceneAsync(@"Assets/Template_4kPortrait_Addressable_Content.unity");
}
}