Coming up with a solution for managing UI elements across different scenes wasn't as trivial as I first expected. It's very easy to attach a canvas to a scene and call it a day. Initially, I had all of my canvases attached to the first scene I expected the player to enter and then simply call DontDestroy(gameObject) on all of the canvas scripts.
So what's the issue? If you allow the user to save and load from other areas, you have to copy/paste a prefab into each of your other scene. This is a trivially easy solution, but it's too dirty for my liking, instead, we should dynamically create and manage the UI elements via a UI manager.
The first step would be to create an empty object in our loading screen (the loading screen will always be accessed before gameplay starts).
In this case, since we're also going to be appending a bunch of canvases to this empty object, it needs a canvas or stuff just doesn't render properly. Also, make sure to add a reference to your UI element prefabs:
And the start script for the UIManager script:
void Start()
{
if (allCanvases == null)
{
DontDestroyOnLoad(gameObject);
foreach (GameObject prefab in prefabsToInst)
{
GameObject toAdd = Instantiate(prefab);
toAdd.name = prefab.name;
toAdd.transform.SetParent(transform);
uiCanvases.Add(toAdd);
}
}
else
{
Destroy(gameObject);
}
}
Each canvas appends itself to the UIManager and therefore does not get destroyed on scene change. All specific behavior for each individual canvas can be handled in the individual UI component's scripts. Blamo! That's it! Crisis averted, we can now navigate between scenes and know that our UI manager is now empowered to show canvases, hide them, etc.
Note: This article was originally published as a blog entry here on GameDev.net by Whistling Alpaca Games.
This is the same way as managing any gameObject between scenes.
If you need to retain information between scenes use a datamanager object and use that to instanciate information in the new scene.
The obvious thing to watch however, you can get yourself unstuck if you're developing scenes independently that you dont have duplication of non-destroyed objects on load... can be worked around using instances.