Coding Quests
The Scroll Library
Tutorials

Godot 4 Main Menu and Pause Menu Tutorial

June 16, 20265 min read

A game without a main menu feels like a prototype. A game without a pause menu feels broken the first time someone needs to step away. Both are quick to build in Godot 4, and there's one detail about pausing that trips up nearly everyone, so let's get it right.

The main menu

A menu is just a scene made of UI nodes. Start with a Control as the root, add a VBoxContainer to stack things vertically, and drop in a few Button nodes: Play, Options, Quit.

Then a script on the root that handles the buttons:

GDScript
extends Control
func _ready() -> void:
$VBoxContainer/PlayButton.pressed.connect(_on_play)
$VBoxContainer/QuitButton.pressed.connect(_on_quit)
func _on_play() -> void:
get_tree().change_scene_to_file("res://scenes/Level.tscn")
func _on_quit() -> void:
get_tree().quit()

change_scene_to_file() swaps the whole current scene for your level. get_tree().quit() closes the game. Set this menu scene as your main scene in Project Settings and it's the first thing players see.

You can also connect buttons in the editor through the Node panel, but connecting in code keeps all the behavior in one searchable place, which I prefer once a menu has more than a couple of buttons.

The pause menu and the gotcha

Here's the trap. You call get_tree().paused = true, and then realize your pause menu is also paused, so its buttons don't respond. The game's frozen and so is the thing meant to unfreeze it.

The fix is process_mode. Every node has one, and it decides whether the node keeps running while the tree is paused. Set your pause menu to keep working:

  1. Select your pause menu's root node.
  2. In the Inspector, find Process, then Mode.
  3. Set it to When Paused (or Always).

Now the menu runs even while everything else is frozen.

GDScript
extends Control
func _ready() -> void:
hide()
# Make sure this menu keeps processing while the game is paused
process_mode = Node.PROCESS_MODE_WHEN_PAUSED
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
toggle_pause()
func toggle_pause() -> void:
var paused := not get_tree().paused
get_tree().paused = paused
visible = paused
func _on_resume_pressed() -> void:
get_tree().paused = false
hide()
func _on_quit_to_menu_pressed() -> void:
get_tree().paused = false # always unpause before changing scenes
get_tree().change_scene_to_file("res://scenes/MainMenu.tscn")

ui_cancel is the built-in Escape action, so pause works out of the box. The one thing to remember: always set paused = false before changing scenes, or your next scene loads frozen.

A small polish pass

A pause menu that pops in instantly feels abrupt. Fade it in with a quick tween, and consider a dim background panel so the game clearly recedes:

GDScript
func show_paused() -> void:
modulate.a = 0.0
show()
create_tween().tween_property(self, "modulate:a", 1.0, 0.15)

Where this fits

Menus, scene changes, and pausing are the connective tissue that turns a pile of scenes into a game someone can actually sit down and play. If you're still building the systems those menus wrap around, the free Inventory System quest is a good place to build a real one, UI and all, with the same Control nodes you just used here.

FAQ

How do I pause a game in Godot 4?

Set get_tree().paused = true. The catch is that your pause menu pauses too, so set its process_mode to When Paused or Always in the Inspector. That keeps the menu responsive while the rest of the game is frozen.

Why doesn't my pause menu work when the game is paused?

Because the menu is paused along with everything else. Its buttons can't respond. Change the menu node's Process Mode to When Paused (or Always) so it keeps running while get_tree().paused is true.

How do I switch scenes in Godot 4?

Call get_tree().change_scene_to_file("res://path/to/Scene.tscn"). It unloads the current scene and loads the new one. Always unpause first with get_tree().paused = false if you're changing scenes from a pause menu, or the new scene starts frozen.

godottutorialuimenu

Reading is the map. The quest is the territory.

Build this for real in the Inventory System Quest. It's free, no card needed.

Start the Quest
Written by Coding Quests

We teach Godot 4 by making you build complete systems: inventories, save systems, souls-like controllers, enemy AI. The scrolls are free. The quests are where it sticks.