Unity Scene Management – Creating Project SceneManager

March 16, 2019

Advancing Tower Defense Tutorial

Altering Scene Format

Youtube – Unity- Scene Manager and Keeping Objects when Loading/Unloading

By: Egon Everest

Following in the footsteps of the FAR team from a Unite 2017 talk, I wanted to update my scene management in the tower defense tutorial to match that from the talk. To begin, I wanted to create a general Logic Scene to hold all of my managers and a Base Scene to hold general assets consistent between levels.

To start I needed to break up my current level scenes into their various parts since these will have all of the basics for every scene we are attempting to construct…

Since the Scene Fader will be used constantly as a way to transition between any and all scenes, this was included in the Logic scene that will persist the entire time the game is open. To make this accessible to all the other scenes and scripts however, I chose to have its script create a public static instance of itself. This was copied directly from the way the BuildManager was setup (creating a simple sort of singleton reference from the Brackeys tutorial):

public static SceneFader sceneFaderInstance;

private void Awake()
{
if (sceneFaderInstance != null)
{
Debug.Log(“More than one Scene Fader in scene”);
return;
}
sceneFaderInstance = this;
}

This way I could just go into all the scripts that had a public reference for the Scene Fader to drag into in the Inspector, and have the sceneFader variable to be set to SceneFader.sceneFaderInstance at Start instead of relying on the public reference.

Next I determined that I needed to figure out how to manage loading/unloading these various scenes now. Using basic Unity scene management, my scripts just load one scene at a time and unload all the current scenes. So even though I could test this by dragging in a Level scene and a Logic scene at the same time to make sure the new setup worked, everything would be back to loading one scene at a time as soon as I called a basic LoadScene method. To learn this, I went to look for a new tutorial.

I came across a Scene Manager tutorial dealing with loading/unloading objects in a more controlled manner that seemed perfect for what I was looking to do. There is a Scene Manager method called LoadSceneAsync which gives more options for how you load a scene. You give it a build index as well as a LoadSceneMode.

    LoadSceneMode has two options:

  • Single: the basic way Unity loads scenes where it also unloads all other currently loaded scenes
  • Additive: this just additionaly loads the inserted scene; this does not unload any other scenes

The Additive LoadSceneMode is the first step to accomplishing what I am looking for. At this time, I also decided it may make more sense to add some type of SceneManager object to my Logic scene to hold a SceneManager type script to deal with these functions. I did not want to run into any issues with Unity’s built in SceneManager so I just named all of this SceneManagerLite for now. This would use a similar singleton setup as referenced earlir for the BuildManager and the SceneFader.

Continuing along with this tutorial, this scene management method requires you to unload the currently loaded scene as well when needed. To do this, there was a simple Scene Manager method, UnloadScene. This is currently obsolete however but just needs replaced with UnloadSceneAsync. Similarly to LoadSceneAsync, this requires at minimum the build index of the scene you wish to unload.

So when I started to look into changing all of the scripts to fit within this new scene management scheme, I came across the realization that my Scene Fader is basically my Scene Manager Lite already. Every script that deals with changing scenes acceses the Scene Fader first to perform the “FadeOut” method created, which contains both the simple fade effect as well as the actual LoadScene method constantly being used that I wanted replaced. With this discovery, I renamed my Scene Fader to the Scene Manager Lite and made the necessary edits here. This simplified everything as now I could simply just change the FadeOut method to use the LoadSceneAsync and UnloadSceneAsync methods and it would apply to all the existing calls to that method.

I did end up needing to go through each method call and touching them up because the tutorial set the scene loading method up with a string input, and I wanted to change this to an int input to go with the build index. I figured the overall scene layout and build indices were pretty set at this point, so using build index instead of the scene names would be more consistent and easier to work with in the future as I added levels.

Outside Scene Management

Something important to note is that some of the scripts I wanted to update with the new Scene management would actually be referencing build indices for a scene other than themselves. Each of these are in the OverlayCanvas, which is an object I want to keep in the BaseScene, as all of these objects will remain consistent through every level. These are those scripts:

  • CompleteLevel: deals with functionality of UI menu when player successfully defeats a level
  • GameOver: deals with functionality of UI menu when player fails a level
  • PauseMenu: deals with functionality of UI menu when player pauses the game

This means that when they want to inform the SceneManagerLite of what scenes to load/unload, they will actually want to reference the build index of the LevelScene, not the index of their own scene (BaseScene).