UI and HUD
Menus, score labels, buttons, health bars — the stuff that sits on top of the game. Build it in the UI workspace. It is part of the game, not the editor chrome.
UI vs scene objects
| Use scene objects for | Use UI for |
|---|---|
| World characters | Score counters |
| Platforms and props | Menus |
| Physics objects | Buttons |
| Pickups and hazards | Dialog panels |
| World-space signs | Health bars and progress displays |
World objects live on the scene canvas. UI elements live in interface layers that should remain readable across screen sizes.
Common UI elements
| Element | Use |
|---|---|
| Panel | Grouping surface for menu or HUD content |
| Label | Score, timer, prompt text |
| Button | Menu action, retry, start, pause |
| Image | Icon, portrait, decorative game art |
| Progress bar | Health, cooldown, loading, stamina |
| Slider | Settings, volume, adjustable runtime values |
The UI palette adds elements such as Panel, Text, Button, Bar, Slider, and Image.
Inspector sections
Selecting a UI element shows sections based on that element type.
| Section | Edits |
|---|---|
| Element | Name, visibility, input blocking |
| Placement | Anchor and offsets when the parent is not laying out children |
| Sizing | Fixed, fill, or hug sizing inside layout parents |
| Layout | Row, column, grid, spacing, padding, alignment |
| Style | Background, corner radius, text color, font size |
| Content | Text, button event name, bar value, image asset, slider variable |
| Data bindings | Live GameState or component values for text, bars, visibility, opacity |
| World anchor | Pin the UI element to a world object's screen position |
Keep HUD UI compact. A player should understand the important state while still seeing the game.
Binding UI to game state
This is how a score actually shows up on screen.
Select a UI element. Data bindings lists what that element can follow — Text on a Text widget, Label on a button, Value / Maximum on a bar, plus Visible and Opacity on everything.
For each one, pick a Source:
| Source | Use |
|---|---|
| None | Leave it alone |
| GameState | A project variable (score, lives, coins…) |
| Component | A field on a scene object (health on the player, a computed percent on a director) |
| Expression | An old = string. Still runs if you already have one; the picker is the usual path now |
GameState for values the whole game shares. Component for values that live on one object.
A score label is a good first one:
- Add a Text element.
- Data bindings → Text → Source → GameState.
- Value → the variable (
score). - Format → Integer (rounded) for a whole number, Raw if you want decimals.
- Template →
Score {value}—{value}is the number. Wrap it in whatever words you like ({value} pts,{value} seeds).
Leave Visible and Opacity on None until you need them. Source → None clears a binding.
The picker remembers the variable's id, so renaming the display name later does not break the HUD. Scripts write that field with Game.SetNumber("score", …).
For a health bar on a scene object: Source → Component, pick the object and its Health (or custom) component, then Value. If Health lives on the same object as the bar, the Health Bar component is simpler than a UI widget.
Bindings run after gameplay each frame, so the HUD catches up as soon as a script or Flow changes the value.
GameState in the HUD. Score labels use Data bindings → GameState. Flow still reads the same fields with Get Value or =GameState.score. A UI template does not belong on a Flow node — they are different pickers.
UI buttons and Flow
Buttons can trigger Object Flow or Scene Flow.
Examples:
| Button | Graph action |
|---|---|
| Start | Go To Scene: Level 1 |
| Retry | Reset GameState, reload current scene |
| Pause | Show pause panel, stop gameplay timer |
| Shop item | Check currency, subtract cost, add item |
| Close | Hide panel |
Put global navigation in Scene Flow when possible. Put button-specific feedback, sounds, and visual state on the button object.
Buttons expose an Event field. At runtime, pressing the button emits that custom event into the rule system. Listen for the same event name in Scene Flow or Object Flow.
In Play and the exported player, Tab selects the first visible button or slider; Tab / Shift+Tab moves through controls in layout order. With a control focused, arrow keys move focus, Enter / Space activates a button, and Escape clears focus. A controller's D-pad selects and moves between controls, its South button activates, and its East button clears focus. Left/right adjusts a focused slider by 5% of its range. Each press acts once, and input used by a menu stays consumed through release so the same press cannot also trigger gameplay.
Focus skips hidden controls and scrolls the selected control into view. A slider with a bound value is read-only unless its Variable field names the GameState value to change; that command updates GameState before the binding refreshes. These controls use the canvas focus indicator. A screen-reader mirror and a project localization catalog are not available yet.
Previewing over the scene
In the UI workspace, the stagebar Show scene toggle lays out the UI at the same stage bounds used in Play and Preview, composited over the arrange-mode scene (edit camera — not a live Play session). Leave it off to edit on the letterboxed artboard.
Responsive layout
Players may run the game on desktop, tablet, or phone-sized screens.
Do — HUD that survives 375 px
- Score label anchored top-left 12 px, Lives top-right, pause button top-right inset
- Buttons ≥ 44×44 px with 8 px padding, rounded 10 px
- Long text in a Panel with
Rowlayout andgap 8 pxso it wraps - Test at 375 px and 1280 px in fullscreen Play before publishing
Don't — layout that breaks on a phone
- Center-stage HUD that collides with the play area on small screens
- 28 px tap targets the editor can click but a thumb can't
- Fixed 600 px-wide menu panel that overflows on mobile
- Only testing in viewport, never fullscreen
UI organization
Name UI roots clearly:
UI
HUD
ScoreLabel
LivesLabel
PauseMenu
Panel
ResumeButton
RetryButton
Dialog
Portrait
Text
ContinueButtonKeep menus hidden until needed. Use flow graphs to toggle visibility.