Loading Scenes In Unity
Even though loading a different Scene in Unity only requires a single line of code, depending on varying situations there’s quite some to say about how we can utilise Scene Management functionality.
Depending on the size or structure of your game you might want to split the game into different Scenes, each representing a level or a part of a level on its own.
There might be situations where we need to access a specific Scene, like the previous or next Scene. Or maybe we just want to load the Scene with a particular ‘SceneName’.
We may want to display additional loading information on screen like a loading progress bar or some game tips, during the ‘loading time’.
We have quite a few methods provided by UnityEngine.SceneManagement allowing us to manage scene loading behaviour, in this article you’ll be introduced to a few important concepts. In addition we’ll start implementing scene management behaviour to our own space shooter project.
Amongst a few other classes provides by UnityEngine.SceneManagement there are two classes that I swiftly want to highlight; the Scene and SceneManager Class. They help us derive information from our Game Scenes and how we can efficiently manage storing or switching between them.
Run-time data structure for *.unity file.
A few important properties:
- name : Returns the name of the Scene that is currently active.
- path : Returns the relative path of the Scene. Like: “Assets/MyScenes/MyScene.unity”.
- buildIndex : Returns the index of the Scene in the Build Settings.
For more information about the Scene Class, click here.
Scene management at run-time.
This Class has two Static Properties:
- sceneCount : The total number of currently loaded Scenes.
- sceneCountInBuildSettings : Number of Scenes in Build Settings.
The SceneManager provides us with a range of Static Methods allowing us to handle Scene Management. A few examples:
- GetActiveScene : Gets the currently active Scene.
- GetSceneByBuildIndex : Get a Scene struct from a build index.
- GetSceneByName : Searches through the Scenes loaded for a Scene with the given name.
- GetSceneByPath : Searches all Scenes loaded for a Scene that has the given asset path.
- LoadScene : Loads the Scene by its name or index in Build Settings.
- LoadSceneAsync : Loads the Scene asynchronously in the background.
- SetActiveScene : Set the Scene to be active.
For more information about the SceneManager Class, click here.
First of all we need to make sure that the Scene we want to load is included in the ‘Scenes In Build’ List, otherwise it won’t load.
Select File > Build Settings or Ctrl + Shift + B, and drag in the Scene in to the Build Settings List. Alternatively you can add all active scenes to the Build Settings by clicking Add Open Scenes.
Then we need to make a new Script where we want to load our Scenes from. You can call this as you like but I think it’s handy to keep logic that handles scene management separated from other types of behaviour.
In this Script we need to add the UnityEngine.SceneManagement; namespace giving us access to the Scene and SceneManager Class related functions.
To Load a Scene we can call the Static Method Load Scene() and either pass in a Scene Name (string), a Scene Index (int) or a Scene Path (string).
A Scene can be loaded in Single Mode, which unloads the previous Scene immediately upon loading the next Scene. Or, it can be loaded in Additive Mode, keeping both Scenes active at the same time in the Hierarchy while overlapping each other in the Game View. Just declaring a single parameter will execute loading a Scene in Single mode.
When to use which parameter
This depends on the structure of your game and what kind of functionality is needed. A few examples might demonstrate this;
- If the Scene Index number is not the last one, add one to the index and load that scene.
- If the Scene Index number is not the first one, remove one from the index and load that scene.
Just keep in mind that if you load a Scene by its Scene Index, the index number must match the respective Scene in the Builds Settings. However, you can easily rearrange them.
Load Scene vs Load Scene Async
Important to know is that there are two methods available for Loading a scene: Load Scene and Load Scene Async.
Load Scene loads the Scene directly with loading taking place during the next frame. This semi-asynchronous behaviour can cause frame stuttering and can be confusing because load does not complete immediately.
For more information about LoadScene(), click here.
Load Scene Async
Load Scene Async loads the Scene in the background and is spread over multiple frames.
In general, it is recommended to use the Async method since it is much more efficient spreading the loading over several frames instead of one, it works perfectly in a Player Build, however in the Editor itself it might stutter and freeze because the Editor does not support background operations very well.
On the plus it leaves us the option to access the loading process which is useful for when I’ll introduce Loading Screen Behaviour to the game in a second part of this article.
Because Load Scene Async is an Asynchronous Operation, we have the ability to yield information from the loading process (similar to how a coroutine works).
For more information about LoadSceneAsync(), click here.
This being an introduction to SceneManagement in Unity we’ll cover other classes and class properties of interest as we get further into the development process. Yet if you already want more in-depth information you can visit the official Unity Documentation. What’s left for us to do now is to apply some basic scene management functionality to our own game.
To start using the Scene and SceneManager Classes in the Space Shooter Project, I’ll implement a Restart() method which then can be triggered by the Player through a button in case a level restart is wished for.
First I’ll add a new GameManager.cs Script to a new Empty GameObject. This script will contain any information that is related to the Game Logic, for example Game Over Logic, Pause and Play and so fourth.
I can now also remove the game over logic from the Player.cs and add it to the GameManager.cs since we have a separate script for this type of behaviour.
Then, to another new Empty Game Object in the Scene Hierarchy, I attach a script called SceneLoadingManager.cs. This script will handle anything related to Scene Management in our Game.
To the Game Over Window I add two new buttons and updated their text to display as ‘Quit’ and ‘Restart’.
In the SceneLoadingManager.cs I create a public method which can be accessed by the GameManager.cs, responsible for Loading a Scene by Index number.
I also create a method to return the currently active scene which again can be accessed by the GameManager.cs;
Then in the GameManager.cs, we should grab a reference to the SceneLoadingManager.cs, together with the Game Over logic it should look like this;
In the Restart() method we can now request the active scene through the SceneLoadingManager.cs and reactivate it if it’s Game Over.
In the Editor, the GameManager Restart() method should be assigned to the ‘Restart’ Button On Click Event, like so;
In the Player.cs, all what is left to do is to notify the GameManager.cs that the game is over when the Player dies.
Now when the Game is Over, we have the ability to restart the active scene. We did that by fetching the current active scene and reloading it through the GameManager when the restart button is pressed.
This article should provide a firm basis of understanding how UnityEngine.SceneManagement works and how we can use it in our projects to handle scene related functionality. We learnt about loading scenes and how to retrieve information from them, which is a critical step in order for us to add more features to the User Interface System in the future, such as dynamic loading screens or other UI menu’s. I am definitely looking forward to proceed, what about you? Good luck with it!
← Previous | Next →