Creating a simple GameManager using Unity3D

1
14932
5 min read

Using the so called “Game Managers” in games is just as common as eating when making games. Probably every game made has their natural flow: Start -> Play -> Pause -> Die -> Game Over , etc. To handle these different game states, we need a proper manager who can provide a mechanism to know when to change to state “A” to state “B” during gameplay.

In this post we will show you how to create a simple game manager for Unity3D games. We will assume that you have some previous knowledge in Unity, but if you haven’t get the chance to know it, please go to the Official Learn Unity page and get started. We are going to create the scripts using the C# language.

1 – The Singleton Pattern

For the implementation, we will use the Singleton pattern. Why? Some reasons:

  • One instance for all the game implementation, with no possible duplications.
  • The instance is never destroyed on scene changes.
  • It stores the current game state to be accessible anytime.

We will not explain the design of the Singleton pattern because it’s not the purpose of this post. If you wish to know more about it, you can go here.


2 – The GameManager code

Create a new project on Unity and add a first csharp script called SimpleGameManager.cs and add the following code:

using UnityEngine;
using System.Collections;

// Game States
// for now we are only using these two
public enum GameState { INTRO, MAIN_MENU }

public delegate void OnStateChangeHandler();

public class SimpleGameManager {
    protected SimpleGameManager() {}
    private static SimpleGameManager instance = null;
    public event OnStateChangeHandler OnStateChange;
    public  GameState gameState { get; private set; }

    public static SimpleGameManager Instance{
        get {
            if (SimpleGameManager.instance == null){
                DontDestroyOnLoad(SimpleGameManager.instance);
                SimpleGameManager.instance = new SimpleGameManager();
            }
            return SimpleGameManager.instance;
        }

    }

    public void SetGameState(GameState state){
        this.gameState = state;
        OnStateChange();
    }

    public void OnApplicationQuit(){
        SimpleGameManager.instance = null;
    }

}

Explaining the code in parts, we have:

First we are making some enums for easily check the Game State, so for this example we will have:

public enum GameState { INTRO, MAIN_MENU }

Then we will have an event delegate method that we will use as a callback when a game state changes. This is ideal for changing scenes.

public delegate void OnStateChangeHandler();

Moving forward we will have the gameState attribute, that is a getter for the current Game State.

public GameState gameState {get; private set;}

Then we will have our class. Taking a look at the singleton implementation we can see that we will use the Instance static variable to get our Game Manager current instance or create a new one if it doesn’t exists. It’s also interesting to see that we call the DontDestroyOnLoad method in the Game Manager instanciation. On doing that, Unity makes sure that our instance is never destroyed between scenes. The method used to change the Game State is SetGameState, which we only need to pass the GameState enum variable as the parameter.

public void SetGameState(GameState state){
    this.gameState = state;
    OnStateChange();
}

It automatically sets the new gameState for the instance and call the callback OnStateChangemethod.

3 – Creating Sample Scenes

For testing our new Game Manager, we will create 2 Unity scenes: Intro and Menu. The Intro scene will just show some debug messages, simulating an Intro game scene, and after 3 seconds it will change to the Menu Scene were we have the Game Menu code.

Create a new scene called Intro and create a csharp script called Intro.cs. Put the following code into the script:

using UnityEngine;
using System.Collections;

public class Intro : MonoBehaviour {

    SimpleGameManager GM;

    void Awake () {
        GM = SimpleGameManager.Instance;
        GM.OnStateChange += HandleOnStateChange;

        Debug.Log("Current game state when Awakes: " + GM.gameState);
    }

    void Start () {
        Debug.Log("Current game state when Starts: " + GM.gameState);
    }

    public void HandleOnStateChange ()
    {
        GM.SetGameState(GameState.MAIN_MENU);
        Debug.Log("Handling state change to: " + GM.gameState);
        Invoke("LoadLevel", 3f);
    }

    public void LoadLevel(){
        Application.LoadLevel("Menu");
    }


}

You can see here that we just need to call the Game Manager instance inside the Awake method. The same initialization will happen on the others scripts, to get the current Game Manager state.

After getting the Game Manager instance we set the OnStateChange event, which is load the Menu scene after 3 seconds. You can notice that the first line of the event sets the new Game State by calling the SetGameState method.

If you run this scene however, you will get an error because we don’t have the Menu.cs Scene yet. So let’s create it!

Create a new scene called Menu and add a csharp script called Menu.cs into this Scene. Add the following code to Menu.cs:

using UnityEngine;
using System.Collections;

public class Menu : MonoBehaviour {
    SimpleGameManager GM;

    void Awake () {
        GM = SimpleGameManager.Instance;
        GM.OnStateChange += HandleOnStateChange;
    }

    public void HandleOnStateChange ()
    {
        Debug.Log("OnStateChange!");
    }


    public void OnGUI(){
        //menu layout
        GUI.BeginGroup (new Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 800));
        GUI.Box (new Rect (0, 0, 100, 200), "Menu");
        if (GUI.Button (new Rect (10, 40, 80, 30), "Start")){
            StartGame();
        }
        if (GUI.Button (new Rect (10, 160, 80, 30), "Quit")){
            Quit();
        }
        GUI.EndGroup();
    }


    public void StartGame(){
        //start game scene
        GM.SetGameState(GameState.GAME);
        Debug.Log(GM.gameState);
    }


    public void Quit(){
        Debug.Log("Quit!");
        Application.Quit();
    }
}

We added simple Unity GUI elements for this scene just for example. Run the Intro Scene and check the Debug logs, You should see the messages when the Game State is changing from the old state to the new state and keeping the instance between scenes. And there you have it! You can add more GameStates for multiple screens like Credits, High Score, Levels, etc. The code for this examples is on github, feel free to fork and use it in your games!

https://github.com/bttfgames/SimpleGameManager

About this Author 

Ellison Leão (@ellisonleao) is a passionate software engineer with more than 6 years of experience in web projects and contributor to the MelonJS framework and other open source projects. When he is not writing games, he loves to play drums.

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here