Exercise 7 — Screen Flow
GAME 1303-002 · Unreal Engine 5.8 · Week 10 — Tuesday, October 27
In class, 10:30 – 11:45 · 2 points · Submit by end of class
The skill
A prototype opens straight into gameplay. A game has a front door.
Today you build all five screens your game needs, wire them into a flow the player can't get stuck in, and bind the HUD to real values. This is the single change that makes a project stop reading as coursework.
The design skill underneath is subtraction. Every element on your HUD costs the player attention, permanently, for the entire runtime. The question for each one is not "is this useful?" but:
What does the player do differently because this is on screen?
If the answer is nothing, it is costing you attention and returning nothing. Cut it.
By the end of the block you will have: title, HUD, pause, win, and lose — working, navigable both ways, restyled, with one element deliberately removed.
This feeds Milestone 4 — Screen Layout (Week 11), next week. Build it on your own game, not a sandbox.
What you need
- Your own game project
GAME1303_Helpersimported — you needWBP_GameUIand the five screen widgets
We use UMG. The five screens live as separate User Widgets inside a Widget Switcher in
WBP_GameUI.
Part 1 — Get the five screens running (20 min)
1. Add the UI to the level
In BP_GameState's Event Graph, on BeginPlay:
Event BeginPlay
→ Create Widget (Class: WBP_GameUI, Owning Player: Get Player Controller)
→ Add to Viewport
→ Set Input Mode Game And UI · Set Show Mouse Cursor (true)
WBP_GameUI binds to BP_GameState's OnStateChanged dispatcher and switches its
Widget Switcher index automatically.
2. Press Play
You should get a title screen. Click START and gameplay begins.
If nothing appears, confirm the widget was actually added to the viewport and that its
Z-order isn't behind another widget.
3. Verify the flow
Walk the whole thing:
- Title → START → gameplay
- Esc → pause → RESUME → back to the same game state
- Pause → RESTART → level reloads
- Reach your goal → win screen
- Die → lose screen
- Every screen → QUIT TO TITLE → title
Click every button. A button that does nothing is a dead end, and dead ends cost a point in the milestone. The helper wires nine uniquely-named buttons; if one does nothing, its name in the UXML no longer matches the one in UIManager.
✅ Checkpoint 1 — all five screens reachable, every button responds, no dead ends.
Part 2 — Make the HUD live (15 min)
4. Wire real data
The HUD must read from your actual game, not show a fixed number.
- Your player needs
BPC_Health. - Your level needs
BP_Scoreif you're tracking score.
WBP_HUD binds to OnHealthChanged and OnScoreChanged on Construct. Take damage — the bar should move.
Bind to the dispatcher, not a property binding. Property bindings on a Progress Bar poll every single frame and teach the wrong habit; they also quietly cost performance in a packaged build.
A HUD that looks right in a screenshot but doesn't move during play is a hard-coded HUD, and that is exactly what the milestone checks.
5. Test it under pressure
Play until you nearly die. Can you read the health bar while dodging? Test it over the busiest part of your level, not an empty corner. Most HUDs are designed against a blank background and become invisible in play.
✅ Checkpoint 2 — health bar and score change during play.
Part 3 — Restyle it (25 min)
The starter UI is deliberately plain. Shipping it unchanged loses the design point here and in the milestone.
6. Change the accent colour
The helper pack ships WBP_ButtonStyle with a single AccentColor variable. Change it once and every primary button updates.
Start here — it's the highest-return edit available.
7. Change the type
Import a .ttf (right-click → Import), then create a Font Face and a Font asset. Assign it in each widget's Text style, or better, set it once in a shared style.
Type does more for perceived polish than any other single change. A free game font from Google Fonts will make your UI look deliberate.
Then adjust your title's size and letter spacing in the Text block's Appearance section. Wide letter-spacing on a title reads as considered; default spacing reads as untouched.
8. Lay it out
UMG uses anchors + slots. The three things that matter:
- Anchor each element to the corner it belongs to, not to the centre
- Use Size Box and Spacer rather than nudging pixel offsets
- Set Alignment so the anchor point sits on the element's own corner
Rules that are actually graded:
- Nothing critical within 5% of the screen edge. Anchor with a margin; don't pin flush to the corner.
- One font, one button style, one spacing rhythm across all five screens.
- Contrast tested against your busiest background.
9. Put the controls on the title screen
ControlsText already exists in WBP_Title. Fill it in with your real controls.
This single label is worth real points in the Week 15 build rubric, because it is the difference between a stranger playing your game and a stranger closing it.
✅ Checkpoint 3 — accent, type, and layout deliberately changed; controls listed on the title screen.
Part 4 — Cut one element (10 min)
10. Justify every HUD element
List everything on your HUD. For each, answer in writing: what does the player do differently because this is on screen?
| Element | What changes because of it |
|---|---|
| Health bar | I retreat when it's low |
| Score | ...nothing, actually. I never look at it mid-play. |
| Combo | I keep chaining to hold it |
| Timer | I skip the optional room |
11. Delete the weakest one
There is always one. Remove it from the UXML.
Then play. The screen will feel better — cleaner, calmer, easier to read at speed. That feeling is the entire lesson of this exercise.
If an element is genuinely needed but only sometimes, consider showing it only then: a score that appears for two seconds when it changes costs nothing the rest of the time.
12. Write your notes
Docs/Ex07_notes.txt:
Screens: title, HUD, pause, win, lose — all reachable both directions.
Restyle:
accent rgb(255,200,60) -> rgb(90,200,255) (matches my ice theme)
font default -> "Silkscreen" (pixel, matches 32px sprites)
title 64px, letter-spacing 6 -> 48px, letter-spacing 12
HUD justification:
health bar -> I retreat when it's low. KEPT
score -> nothing. Never looked at it in play. CUT
dash icon -> I wait for it before committing. KEPT
What I cut and why:
The score label. I played five minutes watching for when I'd look
at it and I never did — my game isn't about score, it's about
surviving the room. Cutting it left the top-right corner empty, so
I moved the dash cooldown icon there where I actually look.
Readability: tested over the lit corridor (my brightest area). White
text vanished, so HUD text now has a 2px black shadow.
✅ Checkpoint 4 — one element cut with a justification, readability tested over the busiest area.
Part 5 — Build and submit (5 min)
13. Package into MyGameName/PC_Builds/Ex07/, then submit
Zip as lastname_ex07.zip: the build, five screenshots (one per screen), and Docs/Ex07_notes.txt.
Canvas → Assignments → Exercise 7.
Rubric — 2 points
| Criterion | Pt | Met when |
|---|---|---|
| Implementation | 1 | Packaged build runs · all five screens present and navigable both directions · no dead ends · pause genuinely freezes gameplay · HUD bound to live dispatcher values · built in UMG |
| Design decision | 1 | Deliberately restyled — accent, type, and layout · controls on the title screen · one HUD element cut with a written justification · readability tested over the busiest area |
Troubleshooting
Nothing renders at all.
The widget was created but never added to the viewport, or it was created on Construct of an actor that isn't in the level.
A button does nothing.
Its OnClicked event was never bound. In UMG each button needs its binding created explicitly — select it, scroll to Events, click + OnClicked.
Buttons don't respond to clicks at all.
Set Input Mode Game And UI and Show Mouse Cursor must both be set, or the click never reaches the widget.
Pause doesn't stop anything.
BP_GameState.Pause sets Global Time Dilation to 0. Anything on a real-time timer ignores it. Also check you aren't pausing with Set Game Paused, which blocks widget input too.
The health bar doesn't move.
Your player needs BPC_Health, and WBP_HUD must find it on Construct — if the widget is created before the pawn is possessed, the Get Player Pawn returns nothing.
Everything is enormous / tiny on another resolution.
Project Settings → User Interface → DPI Scaling Rule → Shortest Side, with a 1080 curve.
If you finish early
- Add a hover sound: bind OnHovered on each button to
BP_SoundPlayer → Play("hover"). - Add a transition — a widget Animation fading a black overlay between screens. Two keyframes and it reads as far more finished.
- Make the HUD diegetic: put the health information on the character instead of in the corner. It's harder, and it's the single most impressive thing you can do in this exercise.
Before next week
Week 11 is Milestone 4 — Screen Layout, 5 points, demoed live — you will be asked to navigate the full flow in front of the room. Read milestone-4-screen-layout.md and run the ⑤ Screen Layout tab of the course checklist.
If you did today's work on your own game rather than a sandbox, the milestone is mostly done.