Gameplay, UI & Audio · Easy · 14 min

Build a Simple Game Loop: Win, Lose, and Restart

Turn a level full of pickups into an actual game: win when you collect them all, lose when the timer runs out, show a result screen, pause the action, and let the player hit Restart — the smallest complete game loop, built from a handful of nodes.

LevelEasy Time~14 min EngineUE 5.4+ Hands-on18 checkpoints

Before this: Make a Collectible: Overlap, Pick It Up, and Score, Your First UMG Widget and HUD: Show Text, an Image and a Health Bar On Screen, Blueprint Variables: Store and Change Values to Drive Behaviour

By the end, you'll be able to
  • Decide a win condition (collect N pickups) and a lose condition (a countdown timer)
  • Show a result widget and pause the game when the round ends
  • Restart the current level cleanly with Open Level
  • Explain why restarting reloads everything to a fresh state

What turns a level into a game

You can have a beautiful level full of pickups, but until there's a way to win and a way to lose, it's a playground, not a game. A 'game loop' is just three honest questions, asked over and over: how does the player win, how do they lose, and what happens then? Answer those three and you've built a complete, tiny game.

In this lesson we'll wire the simplest version of all three. Win = collect every pickup. Lose = run out of time. When either happens, we'll freeze the action, show a quick result screen ('You Win!' or 'Out of Time'), and offer a Restart button that reloads the level fresh. It's only a handful of Blueprint nodes, and it's the exact pattern bigger games use — they just dress it up.

This builds directly on two things you've already done: the pickup that adds to a score, and your first UMG widget. We'll reuse both. If those feel shaky, the prerequisite lessons above are worth a quick re-read first.

The five words this lesson hangs on

Tap a card to flip it

Before you start

You'll get the most out of this if you've already got these in your project. Tick what you have:

  • A level with two or more pickups that add to a score (from the 'Make a Collectible' lesson)
  • A score variable you can read — and ideally a count of how many pickups exist
  • A basic UMG widget you can create and add to the screen (from 'Your First UMG Widget')
  • Five quiet minutes — pausing has one ordering gotcha that trips everyone the first time

Where the logic lives: the Game Mode

Score and win/lose rules don't belong on any single pickup — pickups get destroyed when collected, taking their logic with them. They belong somewhere that outlives them. The natural home is the Game Mode: a Blueprint that acts as the level's referee and stays alive for the whole round.

If you've been keeping the score on a pickup or the player so far, that's fine to start. For this lesson we'll keep the win/lose decision in one tidy place. You can use your project's Game Mode Blueprint, or even keep it on the player character if that's where your score already is — the nodes are identical. What matters is that the logic survives a pickup being destroyed.

Wire the win, the lose, and the restart

Open the Blueprint that holds your score (your Game Mode or player). Work top to bottom — each row stays ticked even if you close the page and come back.

  1. 1Add a 'how many to collect' target

    Make a new Integer variable called something like 'PickupsToWin' and give it a sensible default — say 3 if you have three pickups in the level. This is your win target.

    If you'd rather not count by hand, you can use a 'Get All Actors Of Class' node on Begin Play (pointed at your pickup Blueprint) and set PickupsToWin from its array length. Either is fine; the fixed number is simpler for your first try.

    TipKeep the target as a variable rather than typing '3' into your logic. When you add a fourth pickup later, you change one number instead of hunting through nodes.

  2. 2Check for the win every time the score changes

    Find where your score goes up (the moment a pickup is collected). Right after you add to the score, drag out a Branch node.

    Feed the Branch a condition: Score >= PickupsToWin (use a '>=' / 'Greater Equal' node comparing the two). On True, you've won — we'll fill that in two steps down.

    TipUse 'Greater Equal' (>=), not 'Equal' (==). If anything ever bumps the score by two at once, an exact '== 3' check would sail right past the win and never trigger.

  3. 3Add a countdown timer as the lose condition

    Make a Float variable called 'TimeLeft' (default e.g. 30 for thirty seconds). On Event Tick, do TimeLeft = TimeLeft - Delta Seconds. (Delta Seconds is the small time gap each frame; subtracting it counts down in real seconds.)

    After that subtraction, add a Branch: TimeLeft <= 0. On True, the player has lost — they ran out of time.

    TipEvent Tick runs every single frame, so use 'Delta Seconds' for the subtraction. Subtracting a flat number instead would count down faster on a faster PC — never hard-code frame counts as if they were seconds.

  4. 4Make one 'End Round' function that both paths call

    Create a custom function or Custom Event called 'EndRound' that takes one Boolean input, 'DidWin'. Wire your win Branch (True) into EndRound with DidWin = true, and your lose Branch (True) into EndRound with DidWin = false.

    Doing the ending in one place means win and lose share the exact same shut-down steps — you only write 'pause and show a screen' once.

    TipAdd a Boolean 'RoundOver' variable and set it true at the top of EndRound, with a Branch that early-returns if it's already true. That stops a last-second pickup AND the timer both firing the ending twice.

  5. 5Show the result widget

    Inside EndRound, Create Widget (your result widget class), then Add to Viewport. Use the DidWin Boolean to choose the text — e.g. Set Text on a 'Result' label to 'You Win!' when true, 'Out of Time' when false (a Select node with two strings is the tidy way).

    Put a Button on that widget for restarting — we'll hook it up after the pause step.

    TipSet the widget's Visibility on the restart button to 'Visible' (not 'Hit Test Invisible') so it can actually be clicked. A button you can see but can't click is almost always this setting.

  6. 6Pause the game — and let the mouse click the button

    Still in EndRound, after the widget is on screen, call Set Game Paused (Paused = true). The level freezes but your widget stays up.

    Get the Player Controller and call Set Show Mouse Cursor (true) and Set Input Mode UI Only (or Game and UI) so the player can actually move the mouse and click Restart.

    TipOrder matters: add the widget to the viewport BEFORE you pause. If you pause first and the widget creation is downstream, beginners often find the screen never appears — keep 'show the screen' ahead of 'freeze the game'.

  7. 7Restart on the button click

    Open your result widget's Graph. On the restart Button's 'On Clicked' event, FIRST call Set Game Paused (Paused = false) — you can't cleanly load a level while paused — then call Open Level (By Name) and pass the current level's name.

    To avoid typing the level name (and breaking it if you rename the file), use Get Current Level Name and feed that into Open Level's Level Name input.

    TipOpen Level reloads everything from scratch: pickups reappear, the score resets, the timer is full again. That clean wipe is exactly why 'load the level you're in' is the most reliable restart for a beginner.

Two honest ways to restart

Open Level (By Name) with the current level's name reloads the whole level from disk. Everything resets to its starting state — destroyed pickups come back, the score is zero, the timer is full.

It's a hard reset, so it's bulletproof and easy to reason about. The only cost is a brief load. For a small learning level that's instant, which is why it's the go-to restart here.

Why does collecting all the pickups, then restarting, magically make them appear again with no extra code?

Console commands for testing the loop fast

console
RestartLevel    ; instantly reload the current level (same effect as your button)
slomo 0.2       ; slow time to 20% so you can watch the timer hit zero
slomo 1         ; back to normal speed
stat fps        ; confirm the result screen isn't tanking your frame-rate
Press the backtick key (`) during Play to open the console, type a command and hit Enter. Handy while you tune the win target and timer.
ChallengeTry it yourself

Add a second way to win OR a second way to lose. Easiest options: a 'hazard' trigger that ends the round with DidWin = false the moment the player overlaps it, or a small bonus pickup that adds 2 to the score instead of 1 — then prove your '>=' win check still works because you used Greater Equal, not Equal.

Hint 1

A hazard is just a pickup in reverse: same On Component Begin Overlap → Cast to the player, but instead of adding score, call EndRound with DidWin = false.

Hint 2

A bonus pickup is your normal pickup with the score addition changed from 1 to 2 — no other change needed.

Hint 3

After adding the bonus, deliberately let the score jump past your target to confirm the win still fires (this is what '>=' protects you from).

QuizCheck yourself

1You want a countdown timer as your lose condition. On Event Tick, what should you subtract from TimeLeft each frame?

2Your result screen shows, but clicking the Restart button does nothing. What's the most likely cause?

3Why is 'Open Level' with the current level's name such a reliable way to restart for a beginner?

You can now

If you can tick all four, you've built a complete game loop:

  • Define a win condition (Score >= PickupsToWin) and a lose condition (TimeLeft <= 0)
  • Funnel both into one EndRound event that pauses and shows a result widget
  • Pause the game and still let the player click a button
  • Restart the round cleanly with Open Level and the current level's name
Finished the steps?

Mark this lesson complete

We'll remember it on your Academy page and unlock the next lesson below.

Next lesson →Save and Load Your Game: SaveGame Objects in Blueprints

Questions beginners ask

Should the win/lose logic go on the Game Mode, the player, or a pickup?

Not on a pickup — pickups get destroyed when collected and their logic dies with them. Put it somewhere that lives for the whole round: the Game Mode is the classic, tidy choice (it's the level's referee), but the player character also works fine if that's where your score already lives. The nodes are identical either way.

After I pause, the whole screen is frozen and I can't click anything. How do I fix it?

Set Game Paused freezes gameplay but not your UI. You still need to get the Player Controller, call Set Show Mouse Cursor (true), and set the input mode to UI Only (or Game and UI). Then your mouse can move and your Restart button becomes clickable.

Do I have to type my level's name into Open Level by hand?

You can, but it breaks if you ever rename the level file. The safer way is the Get Current Level Name node fed straight into Open Level's Level Name input — it always restarts whatever level you're actually in, no hard-coded string to maintain.

How is this different from saving and loading a game?

Completely different. Restarting (Open Level) throws away the current run and reloads a fresh level — it's the opposite of saving. Saving captures state (score, position, progress) to disk so you can resume it later. That's its own topic, covered in the Save and Load Game Basics lesson.

Get the next lessons as they land

New Academy lessons, UE5 tips and tool releases — straight to your inbox. No spam, unsubscribe anytime.

Report a bug