Executing first scene in build settings when pressing play button in editor?

I’m using scripting defines to toggle between, e.g.

#if START_FROM_SPECIFIC
EditorSceneManager.playModeStartScene = theScene;
#else
EditorSceneManager.playModeStartScene = default;
#endif

Then define it in Project Settings → Player → Scripting Define symbols as START_FROM_SPECIFIC;

Alternatively, its possible to expose it as MenuItem toggle, and save from which to load by using EditorPrefs.

Something like (pseudocode):

#if UNITY_EDITOR
   public static class StartupSceneExt {
      private const string MenuName = "Tools/Start From Scene";

      // 1. Perform default initialization / set playmode scene via constructor (or InitializeOnLoad), 
      // but load path from EditorPrefs instead or use default if not set
      // 2. Setup initial toggle state (via Menu.SetChecked)

      // Then define menu item
      [MenuItem(MenuName)]
      private static void ToggleScenes() {
         bool isActive = !EditorPrefs.GetBool(*key*);
         EditorPrefs.SetBool(*key*, isActive);

         // 3. Modify from which scene to start, save scene path to Editor Prefs.

         // 4. This changes menu toggle state
         Menu.SetChecked(MenuName, isActive);
      }
   }
#endif
2 Likes

Okay thanks, it makes a bit more sense ! That’s a lot of stuff I didn’t know I could do :smile:
Didn’t understand everything, but I’m glad I have your example as referance to figure it out.

1 Like

I’ve created a UPM package that solves this.
https://github.com/STARasGAMES/unity-main-scene-auto-loading

It’s a feature-rich and extendable solution.

Settings windows:

3 Likes

Hi all, can you make it to work with playmode tests?
What I found is that when you start your test in playmode, it jumps to your default scene previously set. It seems also that once playModeStartScene is set, it can’t be reset until an editor restart.

1 Like

You can set it to null :slight_smile:

I think the best solution would be to place an additional button near playmode button that will trigger entering playmode from main scene.
Somewhere here:
7667599--957358--upload_2021-11-18_12-59-12.png

3 Likes

It doesn’t seem to work either.

Another issue with multiscene and playmode tests is that, in case you run your playmode tests with more than a scene loaded, once you return you find you get only 1 scene loaded back and the rest were removed.

1 Like

i use this, put it in Editor Folder:

using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;

[InitializeOnLoad]
public class DefaultSceneLoader : EditorWindow
{

    private const string defaultScenePath = "Assets/Scenes/Preload.unity";

    static DefaultSceneLoader()
    {
        EditorApplication.playModeStateChanged += LoadDefaultScene;
    }

    static void LoadDefaultScene(PlayModeStateChange state)
    {
        if (state == PlayModeStateChange.ExitingEditMode)
        {
            if (EditorSceneManager.GetActiveScene().path != defaultScenePath)
            {
             
                PlayerPrefs.SetString("dsl_lastPath", EditorSceneManager.GetActiveScene().path);
                PlayerPrefs.Save();

                EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();

                EditorApplication.delayCall += () =>
                {
                    EditorSceneManager.OpenScene(defaultScenePath);
                    EditorApplication.isPlaying = true;
                };

                EditorApplication.isPlaying = false;
            }
        }

        if (state == PlayModeStateChange.EnteredEditMode)
        {
            if (PlayerPrefs.HasKey("dsl_lastPath"))
            {
                EditorSceneManager.OpenScene(PlayerPrefs.GetString("dsl_lastPath"));
            }
        }
    }
}
2 Likes

Thanks pezezzle! That worked flawlessly and honestly I do not know how I have lived without it.

Your code had an issue when first loaded from wrong scene, exited play mode, switched to correct scene, script will switch to wrong scene after exiting play mode because PlayerPrefs was not deleted after switching.
Plus I changed a bit to use scene build index. By default script will recognize 0-indexed scene as bootstrap.

/// <summary>
/// Automatically switches to scene 0 when entering play mode, and back to selected scene when exiting play mode
/// </summary>
[InitializeOnLoad]
public class AutoChangeScene
{
    private static readonly string DefaultScenePath;
    
    static AutoChangeScene()
    {
        EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
        DefaultScenePath = SceneUtility.GetScenePathByBuildIndex(0);
    }

    private static void OnPlayModeStateChanged(PlayModeStateChange state)
    {
        if (state == PlayModeStateChange.ExitingEditMode)
        {
            if (SceneManager.GetActiveScene().path != DefaultScenePath)
            {
                PlayerPrefs.SetString("dsl_lastPath", SceneManager.GetActiveScene().path);
                PlayerPrefs.Save();

                EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();

                EditorApplication.delayCall += () =>
                {
                    EditorSceneManager.OpenScene(DefaultScenePath);
                    EditorApplication.isPlaying = true;
                };

                EditorApplication.isPlaying = false;
            }
        }

        if (state == PlayModeStateChange.EnteredEditMode)
        {
            if (PlayerPrefs.HasKey("dsl_lastPath"))
            {
                EditorSceneManager.OpenScene(PlayerPrefs.GetString("dsl_lastPath"));
                PlayerPrefs.DeleteKey("dsl_lastPath");
                PlayerPrefs.Save();
            }
        }
    }
}

UPD. This is so much better:

[InitializeOnLoad]
public class AutoChangeScene
{
    static AutoChangeScene()
    {
        EditorSceneManager.playModeStartScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(SceneUtility.GetScenePathByBuildIndex(0));
    }
}

@BSGDevelopment look :eyes: