So we are getting to a point in our game where there are stats and bits of information that many of the other scripts need to know about. But it would be a waste of space and resources to go through and make sure that all those scripts have the needed variable to handle the information and that it is constantly kept up to date and matching all the other copies in other scripts. This is where our GameManager class comes in.
For now, the GameManager will be responsible for knowing if the Game is Over and handling player input for things that don’t pertain to controlling the player’s ship, such as restarting the game. But how do we talk to the GameManager without having to set up a reference to it in all the other scripts.
That is where the Singleton design pattern comes into play. A Singleton is a class/script that exists only once in your game and there are no other copies of it being made or referenced. Such classes can be the GameManager, the UIManager, or any other Manager class that you will only have once in the game. This allows us to set a static reference in the Singleton class that all other scripts will be able to see without having a dedicated reference for. Let’s take a look.
This is the basic layout to make a class a Singleton. You need a private static version of the class, in this case GameManager, and we name it _instance. The Static tag makes it so that there is only one version of the variable and no copies can be made of it. _instance will be how it is handled inside the Class.
The next part is a bit more complicated than what we have dealt with so far with variables. We make public static Varaible for the other classes to access called Instance. But since we don’t want them to change what Instance is, we define the permissions as if we were building a method. get sets up what the other classes receive when they do a GameManager.Instance call. In this case, we perform a null check to make sure that _instance is still valid before sending them it to them. By not including a set, we make it so that no one outside of the GamaManager class can change what _instance points to.
In our Awake(), we set _instance to this. That is a self referencing term to allow a script to address some part of itself or what it is attached to. We used before when destroying Lasers and Enemy ships.
Now, that we have the Game Manager set up to be seen by all, what can we do with it. Well, if we create a public method in the class, others can access it.
In this example, We are using the event called method in the UIManager to set the _isGamerOver Bool true in the GameManager.
We can even set up a public Bool in the GameManager to return the GameOver state to any class that needs it.
Here you can see that when we set up the public Bool, it will act as any other bool would when called by other Classes.
This is a powerful way to store the information needed by multiply classes in a single location and goes a long way to keeping your game’s code base clean and organized.
Earlier, I mentioned that we can also use this a place to handle User inputs that don’t involve controlling the ship. Let’s take a quick look at how we are restarting the game.
In the GameManager’s update loop, we added a double IF check. _isGameOver and R key press. Since we use the && symbol instead of &, the IF automatically fails when the first condition is not met and doesn’t waste the cycles to check the second. Very minor optimization, but they add up in larger games, so it is good practice to use them when they are appropriate now.
To work with the Scenes as a whole, we need to use the UnityEngine.SceneManagement namespace. Then we can reload the scene we are in or load other scenes. Since this will be a single scene game, we will just reload the current scene which will reset all the variables and treat it as if the game was just started. The line I used is good for multi-scene games in which you just want to restart the current scene, say for instance a level restart. It checks the the active scene to get its build index ID and passes it to the sceneManager to load.
Now our game can be played forever without having to exit and close the game.