Your levels and combat are in place; now players need to see their health, score, and a way to pause or quit. In this lesson you will build a full UI layer for your 2D action game using Godot 4’s Control nodes: a HUD (health, score, ammo if needed), a pause menu, and a simple main menu.
By the end you will have a reusable UI setup that scales with resolution and stays readable.
1. How Godot 4 UI Works – Control Nodes and Canvas
Godot’s UI is built from Control nodes. They:
- Live in screen space (or as an overlay on top of your game).
- Use anchors and margins so they stay in the right place when the window is resized.
- Can be nested: one CanvasLayer (or root Control) holds the whole UI; inside it you add panels, labels, progress bars, and buttons.
For a game HUD you typically:
- Add a CanvasLayer so the UI draws above the game world.
- Put a root Control (e.g. MarginContainer or a plain Control) as a child.
- Add Label, TextureProgressBar (or ProgressBar), Button, Panel, etc. as children and position them with anchors.
Pro tip: Use a CanvasLayer dedicated to the HUD and set its layer number (e.g. 1) so it always renders on top. Use another CanvasLayer for pause/menus if you want to dim the game behind them.
2. HUD Layout – Health, Score, and Top Bar
Start with a minimal in-game HUD: health and score in one corner.
- Add a CanvasLayer to your main game scene (or the scene that runs during gameplay).
- Add a MarginContainer (or Control) as a child. Set its anchors to the top-right (e.g. anchor preset “Top Right”) and add a small right/top margin so the HUD does not touch the edge.
- Add a VBoxContainer (or HBoxContainer) to group elements.
- Health: Add a Label for “Health” and a TextureProgressBar (or ProgressBar). In code, you will set
valueandmax_valuefrom your player’s health. Optionally use a TextureRect or StyleBox for a custom look. - Score: Add a Label and set its text from your game’s score (e.g.
$ScoreLabel.text = str(score)). - Anchors: Keep the HUD container anchored to one corner (e.g. top-right) so it stays there at different resolutions.
Common mistake: Forgetting to set anchors on the root HUD Control. Without anchors, the UI can sit in the middle or scale incorrectly when the window size changes.
3. Connecting the HUD to Game Data
Your HUD should reflect live data. Two simple approaches:
- Signals: Have the player (or a game manager) emit signals when health or score changes. The HUD scene connects to those signals and updates the ProgressBar and Label.
- Direct reference: The HUD node gets a reference to the player or game manager (e.g. via
get_node()or an autoload) and in_process()or when notified, reads health/score and updates the controls.
Example (conceptual): when the player takes damage, emit player_health_changed(new_value, max_value). The HUD connects to that and sets:
progress_bar.max_value = max_value
progress_bar.value = new_value
Same idea for score: when score changes, update the score Label’s text.
4. Pause Menu – Panel and Buttons
A simple pause menu overlay:
- Add a CanvasLayer (e.g. layer 2) so it draws above the HUD.
- Add a ColorRect that covers the full screen and set its color to semi-transparent black (e.g.
Color(0, 0, 0, 0.6)). This dims the game. - Add a CenterContainer (or Control with center anchors) and inside it a VBoxContainer with:
- A Label “Paused”
- Button “Resume”
- Button “Restart” (optional)
- Button “Quit to Menu”
- By default hide this layer (e.g. set
visible = falseon the CanvasLayer or the root node). - When the player presses the pause key (e.g. Escape), set
get_tree().paused = trueand show the pause CanvasLayer. When they click “Resume”, setpaused = falseand hide the layer. “Quit to Menu” can change to the main menu scene and unpause.
Pro tip: When the scene tree is paused, only nodes with Process Mode set to “Always” (or “When Paused”) still process. So your pause menu buttons should work: set the pause menu CanvasLayer (or its root) to “Process Mode = Always” so input still runs when paused.
5. Main Menu – Title and Start / Quit
A minimal main menu:
- Create a new scene with a Control or MarginContainer as root.
- Add a CenterContainer; inside it put a VBoxContainer with:
- A Label for the game title.
- A Button “Start Game” that loads your first level (e.g.
get_tree().change_scene_to_file("res://levels/level_1.tscn")). - A Button “Quit” that calls
get_tree().quit().
- Set the main menu as the first scene in your project’s Application → Run settings so the game starts there.
- After “Start Game”, you switch to your level scene; from the level you can return to this menu (e.g. from the pause “Quit to Menu” button).
6. Making the UI Look Good – Themes and Fonts
- Theme: Create a Theme resource and assign it to the root Control of a menu or HUD. In the theme you can set default font, font size, colors, and style boxes for Button, Label, etc. This keeps the look consistent.
- Font size: Use a readable size (e.g. 18–24 for HUD labels) and test at your target resolution. Godot’s Label supports auto-sizing; you can also enable “Autowrap” for longer text.
- Colors: Use high contrast (e.g. white or yellow text on dark semi-transparent panels) so the HUD is readable over busy backgrounds.
7. Mini-Challenge – Build Your Complete UI
- Implement the HUD (health + score) and connect it to your player/game state.
- Add the pause menu and wire Resume / Quit to Menu.
- Add (or refine) the main menu with Start and Quit.
- Test at two different window sizes to confirm anchors keep the HUD and menus in the right place.
8. Troubleshooting
- UI not visible: Check that the CanvasLayer is a child of the right node and that nothing is drawing on top of it. Ensure the root Control and its children have non-zero size or correct anchors.
- Buttons not working when paused: Set the pause menu’s process mode to “Always” (or “When Paused”) so it still receives input when the tree is paused.
- HUD in wrong place: Adjust the root HUD Control’s anchor preset and margins. Use the 2D editor’s anchor tools to preview different resolutions.
9. Recap and Next Step
You now have:
- A HUD showing health and score, driven by game data.
- A pause menu with Resume and Quit to Menu.
- A main menu with Start and Quit.
Next up is Lesson 9: Audio System and Sound Design – adding sound effects and music so your action game feels complete. Use the course navigation to continue when you are ready.
For more on Godot UI, see our Godot UI System guide and Control nodes in the official docs.