Scene Transitions
When transitioning from one scene to another you usually want your character items to carry on from the previous scene. There are many ways to achieve this. Each solution below has pros and cons, so make sure to read thoroughly to know which ones suit you best.
When transitioning scene you must choose whether or not you which to carry over the managers, player, and/or UI. If the character is not carried over between scenes you may choose to save the game before unloading the current scene and load the game when the new scene is loaded.
It is important to understand how the Save System Manager works. The Save System Manager saves and loads all Saver data. When changing the scene the Save System Manager will be initialized first. The Savers will each be initialized as the execution order defines. This means that the Save System Manager may be told to load data while the savers are not yet registered to the Save Manager. Therefore the Saver component must load the save data in its start function. This is particularly important for the Inventory Saver.
If you wish to use the Auto Save On Scene Unload and Auto Load On Scene Load you must set each saver to Load On Start and Save On Destroy. Since the Savers can be initialized after the save is loaded, they might not have loaded the save data as the Save System Manager did not know of its existence in the scene. The Scene Unloaded event is sometimes called after the GameObjects have already been destroyed, which requires the Savers to be saved before they are destroyed.
You can manually choose when to save and load the data when unloading/loading scenes. This will give you the most control over how the items saved and loaded. A coroutine can be used to wait a frame between the scene loading and the Load function call to make sure the Saver components are registered to the manager. Learn more about the save feature here.
Each Scene has Everything
This is a naive approach where each scene contains all the components you need in your game: Character, UI, Game Managers, etc. Each time you unload the previous scene completely and load the new one from scratch. Before switching to the next scene save the game, and once the next scene is loaded wait a frame to allow all objects to initialize and then load the save data.
Pros:
- Easy to set up
Cons:
- Does not scale well, make if one of the values is changed, all the scenes need to be updated.
Have a Starter Scene
With this approach none of the scenes have the managers except for the starter scene. Make sure the managers GameObject is set as DontDestroyOnLoad such that they stay when transitioning scenes. The character and UI can also be part of GameObjects to load at start and never destroy.
Pros:
- More efficient load and initialize the managers (and the inventory database) only once at the very beginning instead of each scene.
Cons:
- The only way to test your scenes will be to load the “Start” scene before switching to the scene you wish to test.
- Coming back to “Start” scene from any level will cause the managers to be duplicated causing errors.
Smart Managers Load Component
Using a similar approach to option 2. Except each scene has a custom component that checks if the managers are loaded if not you may load a prefab or a scene with all your managers.
Pros:
- More efficient load and initialize the managers (and the inventory database) only once at the very beginning instead of each scene.
- Each scene can now be tested without having to manually load a “Start” scene.
Cons:
- Slightly less intuitive.
- Requires custom code.
You’ll need to bump the Execution Order of that component to -500 in the project settings to make sure it is called before anything else.
Here is an example of a component which will load the managers:
public class SceneLoaderManagerExample : MonoBehaviour { [SerializeField] protected GameObject m_ManagerPrefab; [SerializeField] protected int m_ManagerSceneBuildIndex= - 1; private void Awake() { if (!InventorySystemManager.IsNull) { //This gameobject is only needed to load the managers remove it once it is done. Destroy(gameObject); return; } // Instantiate a prefab of managers (Make sure to DontDestroyOnLoad). if (m_ManagerPrefab != null) { var managers = Instantiate(m_ManagerPrefab); //Optional don't destroy on load here instead of within the manager components //DontDestroyOnLoad(managers); } //Instead of a prefab load an additive scene with the manager (Make sure to DontDestroyOnLoad). if (m_ManagerSceneBuildIndex >= 0) { SceneManager.LoadScene(m_ManagerSceneBuildIndex, LoadSceneMode.Additive); } //This gameobject is only needed to load the managers remove it once it is done. Destroy(gameObject); } }