GDKB

Game State

Intermediate25 Minutes readUpdated July 21, 20263 related concepts

Game state is the current mode or phase the game is in — main menu, playing, paused, game over — and the rules governing what's allowed to happen in each one. Explicitly tracking and checking game state is what stops the player from moving their character while the game is paused, or what makes the pause menu appear only when gameplay is actually running, rather than every system independently guessing whether it should be active right now.

On this page

Game State

Summary

Game state is the current mode or phase the game is in — main menu, playing, paused, game over — and the rules governing what's allowed to happen in each one. Explicitly tracking and checking game state is what stops the player from moving their character while the game is paused, or what makes the pause menu appear only when gameplay is actually running, rather than every system independently guessing whether it should be active right now.

Why This Matters

Without an explicit, shared understanding of "what mode is the game currently in," every system has to independently figure out whether it should be doing anything — should the player's movement script respond to input right now? Should enemies keep attacking? Should the timer keep counting down? Answering that question separately, and potentially inconsistently, in a dozen different scripts leads to bugs like a character still moving while a pause menu is open, or a death animation playing while the win screen is already showing. A single, explicit game state that every relevant system checks (or reacts to changes in) keeps the whole game's behavior consistent.

Mental Model

Game state is a stoplight everyone on the road obeys, not each driver guessing independently whether it's safe to go. A busy intersection without a shared signal would require every driver to negotiate individually with every other driver, every time — chaotic and unreliable. A stoplight gives everyone the same, unambiguous, shared answer to "should I be moving right now," and every driver's behavior is consistent because they're all reacting to the same signal. A game's state serves the exact same role for every system in the game.

Core Explanation

  • Game state is usually represented as a small, closed set of named modes. An enum GameState { MainMenu, Playing, Paused, GameOver } captures the complete set of modes a game can be in — using an enum rather than loose booleans (isPaused, isGameOver) avoids contradictory combinations like both being true at once.
  • Systems check or react to the current state rather than deciding independently. Player input handling checks "is the current state Playing?" before responding to movement keys; it doesn't maintain its own separate notion of whether the game is active.
  • Transitions between states are usually the interesting, rule-governed part. Moving from Playing to Paused might pause the game loop's simulation time, show a UI panel, and stop enemy AI — a state transition is often a specific, deliberate sequence of actions, not just flipping a label.
  • State changes are commonly broadcast as events, letting interested systems (UI, audio, AI) react without the state manager needing to know about every one of them directly — a direct application of [[CON-0024]].

Syntax / Theory

C# (Unity)

csharp
public enum GameState { MainMenu, Playing, Paused, GameOver }

public class GameStateManager : MonoBehaviour
{
    public static GameState Current { get; private set; } = GameState.MainMenu;
    public static event Action<GameState> OnStateChanged;

    public static void SetState(GameState newState)
    {
        Current = newState;
        OnStateChanged?.Invoke(newState);
    }
}
csharp
public class PlayerMovement : MonoBehaviour
{
    void Update()
    {
        if (GameStateManager.Current != GameState.Playing) return; // Guard on shared state.
        HandleMovementInput();
    }
}

C++ (Unreal — Game State / Game Mode)

cpp
UENUM()
enum class EGameState : uint8 { MainMenu, Playing, Paused, GameOver };

UCLASS()
class AMyGameMode : public AGameModeBase
{
public:
    void SetGameState(EGameState NewState)
    {
        CurrentState = NewState;
        OnGameStateChanged.Broadcast(NewState);
    }

private:
    EGameState CurrentState = EGameState::MainMenu;
};

Unreal has a built-in AGameStateBase/AGameMode framework specifically for this responsibility — a purpose-built version of the same enum-plus- broadcast pattern shown here, integrated with Unreal's networking and level-transition systems.

Unreal Blueprint

A Blueprint-implemented Game Mode can expose a Current State variable and a matching Event Dispatcher, letting other Blueprints branch on or react to state changes the same way as the C++/C# examples.

Practical Example

A pause system uses game state both to stop gameplay and to control which UI is visible.

csharp
public class PauseController : MonoBehaviour
{
    public void TogglePause()
    {
        if (GameStateManager.Current == GameState.Playing)
        {
            GameStateManager.SetState(GameState.Paused);
            Time.timeScale = 0f;
        }
        else if (GameStateManager.Current == GameState.Paused)
        {
            GameStateManager.SetState(GameState.Playing);
            Time.timeScale = 1f;
        }
    }
}
csharp
public class PauseMenuUI : MonoBehaviour
{
    void OnEnable() => GameStateManager.OnStateChanged += HandleStateChanged;

    void HandleStateChanged(GameState state) =>
        panel.SetActive(state == GameState.Paused);
}

PlayerMovement, PauseMenuUI, and any future system all agree on exactly one authoritative answer to "is the game currently paused" — GameStateManager.Current — instead of each maintaining its own, potentially inconsistent notion of it.

Common Mistakes

  • Using scattered boolean flags instead of one explicit state. isPaused, isGameOver, isInMenu as separate booleans allow impossible combinations (isPaused == true and isGameOver == true simultaneously) that an enum-based single state makes structurally impossible.
  • Letting individual systems decide independently whether they should be active, rather than checking or reacting to shared state — this is exactly the inconsistency (movement working during pause) game state exists to prevent.
  • Forgetting to reset relevant systems on a state transition. Moving from GameOver back to Playing (a restart) without resetting health, score, or enemy positions leaves stale state from the previous playthrough bleeding into the new one.
  • Overloading a single game state enum with unrelated concerns. Cramming both "what screen is showing" and "what difficulty is selected" into one state value conflates two independent axes that should be tracked separately.

Game Development Example

A multi-phase boss fight uses its own local state (distinct from the overall game state) to control which phase's behavior is currently active.

csharp
public enum BossPhase { Phase1, Phase2, Enraged, Defeated }

public class BossController : MonoBehaviour
{
    private BossPhase phase = BossPhase.Phase1;

    void Update()
    {
        switch (phase)
        {
            case BossPhase.Phase1:   RunPhase1Behavior(); break;
            case BossPhase.Phase2:   RunPhase2Behavior(); break;
            case BossPhase.Enraged:  RunEnragedBehavior(); break;
            case BossPhase.Defeated: break; // No behavior — fight is over.
        }
    }
}

This mirrors the overall game state pattern at a smaller scale — the boss fight has its own well-defined set of modes, and every piece of its behavior checks or reacts to the current phase rather than each attack pattern deciding independently whether it should run.

Best Practices

  • Represent game state as a single, closed enum rather than several independent boolean flags.
  • Route state changes through one authoritative place (a manager) rather than letting arbitrary systems mutate state directly.
  • Broadcast state changes as events so interested systems can react without the state manager needing direct references to all of them.
  • Explicitly reset relevant systems on transitions that require it (restarting a level, returning to a menu) rather than assuming a clean slate.

Exercises

  1. Implement a GameState enum with MainMenu, Playing, and Paused, and make a PlayerMovement script only respond to input while the state is Playing.
  2. Take the PauseController example and add a GameOver state that stops enemy AI and shows a game-over UI panel, reusing the existing OnStateChanged event.
  3. You're building a turn-based strategy game with states like PlayerTurn, EnemyTurn, Animating, and Victory. Decide whether this should be one large state enum or several smaller, independent state machines (e.g. a separate "turn" state and "UI" state), and justify the trade-off.
  4. Research the State design pattern (distinct from, but related to, this Concept's "game state") and explain how representing each state as its own class/object, rather than an enum checked everywhere, changes how transition logic is organized.
  • Scenes — game state and scene loading are often coordinated together (loading a GameOver scene, or toggling a state within a persistent gameplay scene), though they solve related but distinct problems.
  • Enums — the natural, structurally-safe way to represent a closed set of named states, preventing the impossible-combination bugs that scattered booleans allow.
  • Events — state changes are commonly broadcast as events so interested systems can react without being directly wired to the state manager.

Further Reading

Related Concepts