Help to understand events and delegates (Game Manager)

Hi everyone,
I’m new to Unity so I have a lot to learn…

I’m trying to set up a game manager for my game, I have been following this tutorial and understood most of it: Creating a simple GameManager using Unity3D | Packt Hub

Now, as per the tutorial, I have a game manager script that is a Singleton, and I have a scene called Intro, that has an empty gameobject with an Intro.cs script.

The issue I have is that when I run the game, the Intro script executes Awake and Start, but the ChangeState function is not either called, or passed to the delegate (not sure about the correct wording).
I cannot really tell where the problem is, and I hope you guys can help me understanding it.

GameManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//list of game states
public enum GameState { INTRO, MAIN_MENU }

//callback to change the gameState
public delegate void OnStateChangeHandler(); 

public class GameManager
{
    protected GameManager() {}
    static GameManager instance = null; //global variable where the gm instance is stored
    public event OnStateChangeHandler OnStateChange; //event to change state
    public GameState gameState { get; private set; } //getter for the current game state

    //getter for the gm instance
    public static GameManager Instance{
        get {
            if (GameManager.instance == null) { //if there is no instance, create one
                GameManager.instance = new GameManager();
            }

            return GameManager.instance; //returns the instance
        }
    }

    //function to change the state
    public void SetGameState(GameState state) {
        this.gameState = state;
        OnStateChange();
    }

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

Intro.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Intro : MonoBehaviour
{
    GameManager gm;

    void Awake() {
        gm = GameManager.Instance;
        gm.OnStateChange += ChangeState;
        Debug.Log("Awake - current state: " + gm.gameState);
    }

    void Start() {
        Debug.Log("Start - current state: " + gm.gameState);
    }

    public void ChangeState() {
        gm.SetGameState(GameState.MAIN_MENU);
        Debug.Log("About to change state to: " + gm.gameState);
        Invoke("LoadLevel", 2f);
    }

    public void LoadLevel() {
        SceneManager.LoadScene(1);
    }

}

Thanks for your support!

To start off the code you are looking in the article seems to have a bug, which is fixed in the Github repo SimpleGameManager/Assets/Scripts at master · bttfgames/SimpleGameManager · GitHub (I’ll leave that as a small challenge for you to figure out :wink: ) However, your problem is that you have no calls to invoke the SetGameState method in your GameManager. If you follow the tutorial to completion this is done in the Menus.cs script.


To explain a little further, the Intro.cs script is a listener to the OnStateChange event. In your Awake method you subscribed to the event with the following code:

 gm.OnStateChange += ChangeState;

This doesn’t invoke the ChangeState method. What you are essentially saying is when the OnStateChange event is “fired” I want to know about it and to handle that event I will call a function on my script i.e ChangeState()

Additionally, you are subscribing to the event and then also calling gm.SetGameState() if you think about it, in this context, this doesn’t really make sense. The event is telling you that the game state has changed and then you are calling the GameManager to tell it to change state (there are possible cases where this may be valid, but it’s a little out of the scope of this tutorial).

I see now, I was actually calling the ChangeState() within the very same function, that’s why it doesn’t make much sense and nothing happens.
_
I moved the gm.SetGameState() in the start function, like in the repo you kindly linked, and now it works as intended.

Thank you very much!