As I said on a previous post, it is very common for Unity3d developers to come up with the idea of a game object in their scenes that will hold components that will act as singletons, right?
Normally we want this game object to be there from the beginning, make some initialization (such as finding entities in the scene) and then be ready to handle our requests. Also, we would like this game object to be persistent so we would like to call DontDestoyOnLoad(this); on it. This approach works very well if you have a single scene in your project as everything is running on the same context, but if you have multiple scenes, say, multiple levels in your game, things can get complicated. Suppose you have a component attached which purpose is to find the most used entities in your game (such as the player) and cache them, allowing other components to access them with a static variable. The problem with multiple scenes arises if you change scene and don’t update the references to your cached game objects.
I’ve using a slightly different approach that threats the whole system as a FSM (Finite State Machine). Let me exaplain:
The first idea is to create a static class that will hold a reference to any manager we have in the game, for example:
As you can see, we have a bunch of things that will let us access those Managers easily, as easy as:
Obviously, those components (like the AudioManager) must be attached to this game object in order for this to work. The idea behind this managers is that they will be “always ready”, like a system service, and that they don’t have any dependencies with any particular scene. For example, the AudioManager is able to play sounds in any scene and situation.
There are other types of managers, those that rely on a particular scene or state in order to work. There is also the problem of the global game state. Introducing your awesome GameManager class:
And it’s loyal companion, the GameState abstract class:
Those classes make up a simple FSM system for the different game states in your game (paused, playing, menu screen, etc.). You should inherit the GameState class to provide your custom states. A state is also a component attached to a game object that is responsible for activating/deactivating each game manager that is dependent on that particular state. For organization, I suggest you attach your states to game objects with the name of the state that are childs of the manager game object, like this:
This way, you can have sub-managers attached to this child objects and everything is perfectly organized.
Hope you find this useful. I will post more information about this soon.