Game State

Last Update: June 20, 2022

This is intended to provide a simple state system for the overall operation of the game levels. Does not apply to the menu screen, is only for "Playing the game" scenes.

Game States

I've included five states, three of which are active during game play. As of this writing nothing actually happens in Preloading, but I've added it just in case. Similarly, the only thing that will happen in "Closing", will be application quit or loading the main menu.

The other states are perhaps self explanatory.

GameState (Events)

The GameState class will send out all of the events, and will be the one class which handles transitioning from one state to another. Here is a selection from the script.

GameState.cs
public class GameState : MonoBehaviour
{
    public static GameState gameState;
        
    private LegendEnums.GameState _gameState = LegendEnums.GameState.Preloading; // Always start at preloading
        
    public Action<LegendEnums.GameState> OnGameStateEntered;

    public LegendEnums.GameState ActiveState
    {
        get => _gameState;
        set => _gameState = value;
    }
        
    //=====================================================================================
    // CYCLE METHODS
    //=====================================================================================

    private void Awake()
    {
        if (gameState == null)
            gameState = this;
        else if (gameState != this)
            Destroy(gameObject);
            
        SetGameState(LegendEnums.GameState.Preloading); // Start with this
    }

    private void Update()
    {
        DoPreloading();
        DoLoading();
        DoGameOn();
        DoSaving();
        DoClosing();
    }
        
    //=====================================================================================
    // SET METHODS
    //=====================================================================================

    public void SetGameState(LegendEnums.GameState newGameState)
    {
        ActiveState = newGameState;
            
        OnEnterPreloading();
        OnEnterLoading();
        OnEnterGame();
        OnEnterSaving();
        OnEnterClosing();
    }

...

    private void DoGameOn()
    {
        if (ActiveState != LegendEnums.GameState.GameOn) return;
        // Global actions will go here, things outside of the other classes.
    }

...

    private void OnEnterPreloading()
    {
        if (ActiveState != LegendEnums.GameState.Preloading) return;
        OnGameStateEntered?.Invoke(LegendEnums.GameState.Preloading);
    }
...
}

LegendMonoBehaviour

Any class which relies on states will be a LegendMonoBehaviour, which is just a MonoBehaviour, which has these methods.

LegendMonoBehaviour.cs
public abstract class LegendMonoBehaviour : MonoBehaviour, IHaveGameState
{
    protected abstract void AwakeSetup();
        
    protected virtual void Awake()
    {
        SubscribeToEvents();
        AwakeSetup();
    }

    public virtual void SubscribeToEvents() => gameState.OnGameStateEntered += GameStateEntered;
    public virtual void GameStateEntered(LegendEnums.GameState gameState) { }
    public virtual void EnterPreloading() { }
    public virtual void EnterLoading() { }
    public virtual void EnterGameOn() { }
    public virtual void EnterSaving() { }
    public virtual void EnterClosing() { }
}

Example Use

This is from Game.cs, the main "Game" class, which acts as a hub for a lot of the other classes. The AwakeSetup() method is called in Awake(), and comes after the SubscribeToEvents method on LegendMonoBehaviour.

Game.cs
...
protected override void AwakeSetup()
{
    if (game == null)
    {
ehaviour        game = this;
        SceneManager.sceneLoaded += SceneLoaded;
    }
    else if (game != this)
    {
        game._firstLoad = false;
        Destroy(gameObject);
    }
            
    UnityEngine.Random.InitState(seed); // Random seed for future game option
}
...

Last updated