Game Loop
Game Loop
Definition: The continuously repeating cycle at the heart of every game, processing input, updating game state, and rendering a new frame, over and over, many times per second.
How It Works
- Each iteration: read player input, update positions/physics/AI based on elapsed time, then render the result to the screen
- Runs as fast as possible, or capped to a target frame rate, tied closely to Frame Rate and Delta Time
- Separating “update” logic from “render” logic lets some engines update game state at a fixed rate while rendering at a variable one
- The loop is usually the very last thing to start after setup/initialization, and it only exits when the player quits or the process is closed
- Everything the player perceives as happening “live” (movement, animation, sound triggers, AI decisions) is driven by code called somewhere inside this loop, once per pass
- Some loops separate concerns further into distinct phases: input polling, fixed-step simulation, variable-step interpolation, and presentation, each with a clear boundary
- A “running” flag or state check gates the loop’s continuation, flipping it false (from a quit event, a fatal error, or reaching a level-complete condition) is the only way the loop naturally ends
Under the Hood
Each pass through the loop body is one frame. A game running at 60 FPS executes this entire cycle, input, update, render, roughly every 16.67 milliseconds.
Worked example 1: counting loop iterations over a play session
- Given: a game runs at a stable 60 FPS for a 10-minute play session
- Step: frames per second × seconds per minute × minutes = 60 × 60 × 10
- Step: 60 × 60 = 3,600 iterations per minute; 3,600 × 10 = 36,000 iterations total
- Answer: the game loop body executes 36,000 times during that session, each one reading input, advancing state, and drawing a frame
Worked example 2: cost of expensive work inside the loop
- Given: a naive implementation recalculates a pathfinding graph for every enemy on every single frame, and that calculation takes 3ms per enemy with 20 enemies on screen
- Step: total per-frame cost from pathfinding alone = 20 × 3ms = 60ms
- Step: at a 60 FPS target, the entire frame budget is only 16.67ms, so pathfinding alone is already more than 3.5x over budget before input, other updates, or rendering happen
- Answer: the frame rate collapses to roughly 1000ms / 60ms ≈ 16 FPS; the fix is to recompute paths only when something changes (the enemy’s target moves, an obstacle appears) instead of unconditionally every frame
Worked example 3: sleeping to hit a frame cap
- Given: a frame’s actual work (input + update + render) finishes in 9ms, and the target is 60 FPS (16.67ms budget)
- Step: remaining time to burn = 16.67ms - 9ms = 7.67ms
- Step: the loop either busy-waits (spins doing nothing, burning CPU and battery) or sleeps for approximately that remaining time before starting the next iteration
- Answer: sleeping (or better, waiting on a vsync signal from the display) uses roughly the same wall-clock time as busy-waiting but at a fraction of the CPU/power cost, which is why production engines avoid naive busy-wait loops for frame capping
Loop Implementation Patterns
| Pattern | How it waits between frames | Trade-off |
|---|---|---|
| Busy-wait | Spins in a tight loop checking the clock | Simple, but wastes CPU and battery |
| Sleep-based cap | Calls a sleep/delay function for the remaining budget | Power-efficient, slightly less precise timing |
| VSync-driven | Blocks until the display signals a refresh | Tight to monitor refresh rate, eliminates tearing |
| Uncapped | No waiting at all, renders as fast as possible | Maximum responsiveness, maximum power draw, can destabilize physics tied to frame rate |
Why It Matters
- Everything in a game, movement, collisions, animation, ultimately happens because the game loop calls the right code every single frame
- The loop’s structure determines how responsive input feels, how consistent physics behaves, and how smooth animation looks
- Understanding where in the loop a given piece of code runs (input phase vs update phase vs render phase) is essential for debugging timing-related bugs
Common Pitfalls
- Tying game logic directly to frame rate instead of elapsed time, causing the game to run faster or slower depending on the hardware it’s running on
- Doing expensive work inside the loop that doesn’t need to happen every frame, silently tanking performance
- Mixing rendering code into the update phase (or vice versa), making it hard to decouple simulation rate from display rate later
- Not capping the loop at all on unthrottled hardware, letting the frame rate run arbitrarily high and wasting battery or GPU headroom for no visual benefit
- Blocking the loop on synchronous I/O (disk reads, network calls) inside update or render, freezing the entire game for that duration
- Letting the update phase run an unbounded number of catch-up steps after a long stall, which can spiral into a “loop of death” where each update takes longer than the last and the game never recovers
- Forgetting to decouple the exit condition from the render call, so a quit request mid-frame still finishes rendering into a partially torn-down state
Comparison
| Loop style | Update timing | Render timing | Typical use |
|---|---|---|---|
| Simple variable loop | Every iteration, variable dt | Every iteration | Small/simple games, prototypes |
| Fixed-step with accumulator | Fixed dt, possibly multiple steps per frame | Every iteration, interpolated | Physics-heavy or networked games |
| Multithreaded loop | Fixed dt on a dedicated simulation thread | Separate render thread, reads latest state | High-performance engines (Unreal, custom AAA engines) |
| Event-driven (non-looping) | Only on incoming events | Only on incoming events | Turn-based or UI-heavy applications, not real-time action games |
Example
A minimal loop looks like:
while (running) {
processInput();
update(deltaTime);
render();
}
repeated dozens or hundreds of times per second. Unity, Unreal, and Godot all hide a far more elaborate version of this same structure behind their editor: Unity calls Update() and FixedUpdate() on every active script each pass, Godot calls _process() and _physics_process(), and both are really just callbacks invoked from the engine’s own internal game loop. Unreal Engine’s equivalent is the Tick() function, called once per frame on every actor that has ticking enabled, driven by the engine’s central game thread loop.
Common Interview Questions
- Why split update and render into separate phases? — so simulation can run at a fixed, stable rate for correctness while rendering adapts to the display’s actual refresh rate
- What happens if update takes longer than the frame budget? — the frame rate drops; if using a fixed-step accumulator, multiple update steps may run before the next render to catch back up
- Why not just render as fast as possible with no loop structure at all? — without a controlled loop, input handling, simulation, and rendering can run out of sync, producing tearing, missed input, or runaway CPU/GPU usage
- What’s the difference between a game loop and an event loop (as in a GUI application)? — a game loop actively drives simulation forward every frame by default, while an event loop mostly sits idle waiting for input events to react to
- Where does a game loop typically get its very first entry point? — after asset loading and world initialization complete, right before control is handed over for the remainder of the program’s runtime
- Why do some loops process input separately from update instead of inline? — to guarantee input is read exactly once per frame and applied consistently, rather than being sampled at inconsistent points scattered through the update code
- What’s the “loop of death” and how is it avoided? — a spiral where update falls behind, tries to catch up with more steps, which takes even longer, falling further behind; avoided by capping the maximum number of catch-up steps per frame and accepting slowdown instead of a full stall
History
Early arcade and console games often ran a loop tied directly to a fixed hardware timer or the video signal itself, since the hardware only ran one game at a known, unchanging clock speed. As games moved to PCs with wildly varying hardware, that assumption broke, motivating the shift toward the input-update-render structure with explicit timing shown above. Modern AAA engines have pushed further still, splitting the single loop into multiple threads: a simulation thread advancing game state at a fixed rate, a render thread building and submitting draw calls, and often a separate job system distributing per-frame work (animation, culling, physics) across many CPU cores, all synchronized around the same conceptual loop.
FAQ
- Does every game genre need a real-time loop? — no, turn-based games often use an event-driven structure instead, only doing work in response to a player action rather than continuously every frame
- Can a game have more than one loop running? — yes, some architectures run a fixed-rate simulation loop and a variable-rate render loop on separate threads, each with its own timing
- What’s the very first and very last thing a game loop does? — first is usually reading the previous frame’s timing to compute delta time, last is checking the running condition to decide whether to iterate again or exit to cleanup
Threading Models in Practice
| Model | How work is split | Trade-off |
|---|---|---|
| Single-threaded | Input, update, render all run in sequence on one thread | Simplest to reason about, caps performance to one core |
| Render/simulation split | Simulation on one thread, rendering on another, synchronized each frame | Better CPU utilization, added synchronization complexity |
| Job-system based | Per-frame work broken into many small jobs distributed across a thread pool | Best scaling on many-core CPUs, most complex to implement correctly |
Related Terms
Referenced by