Tom
Tom

Reputation: 2472

Unity3d - Load a specific scene on play mode

Ok, so I'm working on a small project that has a main menu and 10 levels. From time to time I edit different levels, and want to try them out, however I get a NullPointerException as my levels rely on certain variables from the main menu for the levels to work, which means I have to alter my levels, then load my main menu and play from there.

Is there something that can be done in the Unity Editor to default load a specific scene when you hit Play, and not the scene you're on?

I could obviously resolve this to something like

public bool goToMenu; //set this to true in my levels through inspector

Start()
{
    if (goToMenu)
        //then load main menu
}

but it would be really handy if there was a way to set the default level to load when hitting play mode. I've had a look in Preferences but couldn't find anything.

Thanks!

Upvotes: 22

Views: 23290

Answers (5)

Ronny Bigler
Ronny Bigler

Reputation: 724

i use this 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"));
            }
        }
    }
}

Upvotes: 0

Fattie
Fattie

Reputation: 12363

This is a well-known basic issue in Unity.

There is no good solution unfortunately.

When you click "Play" in a game engine it should of course jump to your preload scene and "Play" from there.

Unfortunately in Unity this does not happen.

Every experienced Unity engineer recommends NOT trying to automate this. But if you must...

/* 
ONLY FOR USE DURING DEVELOPMENT IN THE EDITOR
ONLY FOR USE DURING DEVELOPMENT IN THE EDITOR
ONLY FOR USE DURING DEVELOPMENT IN THE EDITOR

MUST RUN FIRST USING "SCRIPT EXECUTION ORDER" system
MUST RUN FIRST USING "SCRIPT EXECUTION ORDER" system
MUST RUN FIRST USING "SCRIPT EXECUTION ORDER" system

YOU MUST REMOVE THIS SCRIPT BEFORE BUILDING TO PRODUCTION
YOU MUST REMOVE THIS SCRIPT BEFORE BUILDING TO PRODUCTION
YOU MUST REMOVE THIS SCRIPT BEFORE BUILDING TO PRODUCTION
*/

using UnityEngine;
public class DevPreload:MonoBehaviour {

    void Awake() {

        GameObject check = GameObject.Find("__app");
        // "__app" is one of your DDOL gameobject in preload scene
        if (check==null)
            SceneManagement.SceneManager.LoadScene("_preload");
        }
    
    }

The secret is to use

Unity's Script Execution Order system

Simply have that script run before anything and it will do what you want.

HOWEVER - be aware that the Script Execution Order system is an incredibly bad engineering idea which nobody ever uses because it's so flakey.

This "trick" is !!ONLY!! for use during development. Stay sober!

Upvotes: -2

CSaratakij
CSaratakij

Reputation: 1

This is the editor script that I wrote that do exactly what you want. https://github.com/CSaratakij/SceneSelector It has the UI to select a specific scene and option to open the first scene in the build setting when enter the playmode. Might be useful for the future visitor.

Upvotes: 0

Z4urce
Z4urce

Reputation: 516

The easiest way is to set your 0th scene as the default play mode scene:

[InitializeOnLoad]
public class EditorInit
{
    static EditorInit()
    {
        var pathOfFirstScene = EditorBuildSettings.scenes[0].path;
        var sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(pathOfFirstScene);
        EditorSceneManager.playModeStartScene = sceneAsset;
        Debug.Log(pathOfFirstScene + " was set as default play mode scene");
    }
}

Upvotes: 22

3Dynamite
3Dynamite

Reputation: 326

I made this simple script that loads the scene at index 0 in the build settings when you push Play. I hope someone find it useful.

It detects when the play button is push and load the scene. Then, everything comes back to normal.

Oh! And it automatically executes itself after opening Unity and after compile scripts, so never mind about execute it. Simply put it on a Editor folder and it works.

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;

[InitializeOnLoadAttribute]
public static class DefaultSceneLoader
{
    static DefaultSceneLoader(){
        EditorApplication.playModeStateChanged += LoadDefaultScene;
    }

    static void LoadDefaultScene(PlayModeStateChange state){
        if (state == PlayModeStateChange.ExitingEditMode) {
            EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo ();
        }

        if (state == PlayModeStateChange.EnteredPlayMode) {
            EditorSceneManager.LoadScene (0);
        }
    }
}
#endif

Upvotes: 31

Related Questions