GDKB

Game Loop

Beginner20 Minutes readUpdated July 21, 20263 related concepts

The game loop is the continuously repeating cycle that keeps a game running: read input, update the world, render a frame, then repeat — dozens of times per second, for as long as the game is open. Every visible behavior in a game, from a character moving to a menu animating, happens because some code runs inside this loop, once per iteration. Understanding the game loop is understanding what a "running game" actually *is* underneath the graphics.

On this page

Game Loop

Summary

The game loop is the continuously repeating cycle that keeps a game running: read input, update the world, render a frame, then repeat — dozens of times per second, for as long as the game is open. Every visible behavior in a game, from a character moving to a menu animating, happens because some code runs inside this loop, once per iteration. Understanding the game loop is understanding what a "running game" actually is underneath the graphics.

Why This Matters

A program that runs once and stops — read some input, compute a result, print it, exit — cannot be a game, because a game has to keep reacting to a player continuously, for an unpredictable and open-ended amount of time. Without a loop structuring that repetition, there would be no consistent place to check "has the player pressed a key," "where should the enemy be now," or "what should be drawn this instant" — and no guarantee those checks happen often enough to feel responsive. The game loop exists to give every one of those responsibilities a predictable, repeating home.

Mental Model

The game loop is a flipbook being redrawn and reflipped, not a single painting. A single static picture can't show motion — animation comes from showing many slightly-different pictures in rapid succession. A game loop does exactly this: each iteration ("frame") recalculates the world's state —a little bit further along than last time — and redraws it, and doing this fast enough (dozens of times per second) creates the illusion of smooth, continuous motion, even though it's actually a rapid sequence of discrete steps.

Core Explanation

  • Three broad phases repeat every iteration: process input, update simulation, render. Exact naming and ordering vary by engine, but every game loop reads the current input state, advances game logic based on it (and on time passing), then draws the result.
  • The loop runs until the game explicitly stops. Unlike a normal function that returns once its work is done, a game loop's "work" is never finished while the game is running — it's designed to run indefinitely, once per frame, until shutdown.
  • Modern engines hide the raw loop and expose lifecycle callbacks instead. You rarely write while (true) { ... } yourself in Unity or Unreal — the engine owns the actual loop and calls your code (Update, Tick) at the right point inside it every iteration.
  • Update and render are conceptually separate steps, even when they appear to happen "at the same time." Game logic (Update) computing where things should be, and rendering (drawing the current state to the screen) are distinct responsibilities — some engines even run them on different schedules (see [[CON-0034]] and fixed-timestep discussions).

Syntax / Theory

Engine-neutral (pseudocode)

text
Initialize()

while (gameIsRunning)
{
    ProcessInput()
    Update(deltaTime)   // Advance simulation state.
    Render()             // Draw the current state.
}

Shutdown()

C# (Unity)

csharp
public class EnemyAI : MonoBehaviour
{
    void Update() // Called once per frame by Unity's own game loop.
    {
        MoveTowardPlayer();
    }
}

C++ (Unreal)

cpp
void AEnemyCharacter::Tick(float DeltaTime) // Called once per frame by Unreal's loop.
{
    Super::Tick(DeltaTime);
    MoveTowardPlayer(DeltaTime);
}

Both Update() and Tick() are the engine handing control to your code at a fixed point inside its own internally-managed game loop — you never see the while loop itself, but every frame, it calls back into your code exactly once.

Practical Example

A simple countdown timer displayed on screen has to be recalculated and redrawn every frame, not computed once.

csharp
public class CountdownTimer : MonoBehaviour
{
    public float secondsRemaining = 60f;

    void Update()
    {
        secondsRemaining -= Time.deltaTime; // Advance state, once per loop iteration.
        timerText.text = Mathf.CeilToInt(secondsRemaining).ToString();

        if (secondsRemaining <= 0)
            OnTimeUp();
    }
}

The timer only counts down because Update runs repeatedly — remove the loop, and secondsRemaining would never change after the first read.

Common Mistakes

  • Doing one-time setup work inside a per-frame method. Loading an asset or instantiating an object inside Update()/Tick() re-runs that work every single frame instead of once — one-time work belongs in an initialization callback (Start()/Awake()/BeginPlay()), not the loop body.
  • Assuming the loop runs at a fixed, guaranteed rate. Frame timing varies (see [[CON-0033]]) — code that assumes "this runs exactly 60 times per second" breaks on slower hardware or under heavy load unless it explicitly accounts for variable frame timing.
  • Blocking the loop with a long-running operation. A frame that performs a slow file load or synchronous network call freezes the entire game for that duration, because nothing else in the loop — input, rendering — can proceed until that frame finishes.
  • Forgetting that rendering shows the last completed update, not the in-progress one. Code that expects visual feedback to reflect a change made mid-Update() before that same frame finishes won't see it — rendering happens after update completes for that iteration.

Game Development Example

A day/night cycle system advances gradually every frame rather than jumping instantly between states.

csharp
public class DayNightCycle : MonoBehaviour
{
    public float dayLengthInSeconds = 300f;
    private float timeOfDay; // 0 to 1, representing one full day.

    void Update()
    {
        timeOfDay += Time.deltaTime / dayLengthInSeconds;
        timeOfDay %= 1f;

        UpdateSunRotation(timeOfDay);
        UpdateAmbientLight(timeOfDay);
    }
}

Every frame nudges timeOfDay forward slightly and immediately reflects that change in lighting — this constant re-evaluation, frame after frame, is the game loop doing its job.

Best Practices

  • Put one-time setup in initialization callbacks, and only genuinely per-frame logic inside Update/Tick.
  • Never assume a fixed number of iterations per second — use elapsed time (see [[CON-0034]]) for anything that should behave consistently across different frame rates.
  • Keep per-frame work as cheap as possible — anything expensive inside the loop runs every single frame, and its cost compounds directly into frame rate.
  • Avoid blocking operations (synchronous file/network access) inside the loop; use asynchronous or background-loaded alternatives instead.

Exercises

  1. Write a Blink MonoBehaviour/Actor that toggles a sprite's visibility every 0.5 seconds using Update, and explain which part of your code runs once versus every frame.
  2. Take the CountdownTimer example and move the timerText.text = ... assignment out of Update() into Start() by mistake — run it and describe, in terms of the game loop, why the displayed time never changes.
  3. You're building a loading screen that needs to display a spinning icon while a large asset loads synchronously. Explain, in terms of the game loop, why the spinner will freeze during the load, and propose one way to fix it.
  4. Research "fixed timestep" vs. "variable timestep" game loops and explain, in your own words, why physics simulation code commonly runs in a separate, fixed-rate loop instead of the same loop as rendering.
  • Frame Rate — the game loop's iteration speed, measured in iterations (frames) per second, and the direct consequence of how much work each loop iteration does.
  • Delta Time — the elapsed-time value the loop hands to update logic each iteration, letting behavior stay consistent regardless of how fast the loop is actually running.
  • Input Systems — reading input is one of the game loop's core phases, checked once per iteration alongside updating and rendering.

Further Reading

Related Concepts