Skip to main content
added 123 characters in body
Source Link
Applekini
  • 8.5k
  • 8
  • 37
  • 64

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    // Should probably use a custom delegate type instead of Action
    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// How to change state
if (/* pause pressed */) {
    Game.CurrentState = GameState.Paused;
}

// Inside Start() of mainpause menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState ==!= GameState.PausedPlaying) {
    // Don't do enemy logic while pausednot playing
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    // Should probably use a custom delegate type instead of Action
    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// Inside Start() of main menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState == GameState.Paused) {
    // Don't do enemy logic while paused
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    // Should probably use a custom delegate type instead of Action
    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// How to change state
if (/* pause pressed */) {
    Game.CurrentState = GameState.Paused;
}

// Inside Start() of pause menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState != GameState.Playing) {
    // Don't do enemy logic while not playing
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.

added 73 characters in body
Source Link
Applekini
  • 8.5k
  • 8
  • 37
  • 64

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    // Should probably use a custom delegate type instead of Action
    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// Inside Start() of main menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState == GameState.Paused) {
    // Don't do enemy logic while paused
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// Inside Start() of main menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState == GameState.Paused) {
    // Don't do enemy logic while paused
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    // Should probably use a custom delegate type instead of Action
    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// Inside Start() of main menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState == GameState.Paused) {
    // Don't do enemy logic while paused
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.

Source Link
Applekini
  • 8.5k
  • 8
  • 37
  • 64

I think both current answers are over-complicating the problem. I think a simple solution like this is adequate and much easier to reason about:

public static class Game {
    private static GameState currentState;

    public static GameState CurrentState 
    { 
        get => currentState; 
        set
        {
            PreviousState = currentState;
            currentState = value;
            OnStateChanged?.Invoke(currentState, PreviousState);
        }
    }

    public static GameState PreviousState { get; private set; }

    public static event Action<GameState, GameState>? OnStateChanged;
}

public enum GameState {
    Paused,
    Playing,
    // Etc.
}

This class simply handles the current game state and is responsible of notifying anyone that cares when the game state changes. Usage would look like this:

// Inside Start() of main menu
Game.OnStateChanged += (currentState, previousState) => {
    if (currentState == GameState.Paused && previousState == GameState.Playing) {
        // Open this menu
    } else if (currentState == GameState.Playing && previousState == GameState.Paused) {
        // Close this menu
    }
};

// Inside Update() on an enemy
if (Game.CurrentState == GameState.Paused) {
    // Don't do enemy logic while paused
    return;
}

// etc.

If you prefer for this to live inside a game object instead of a static class you can do that too. Just make this class inherit MonoBehaviour, name it something more reasonable, remove static from the properties, and attach it to a game object that you don't destroy.