Menus
Create main menus, pause menus, and navigation systems.
Introduction
Menus are the first thing players see. This guide covers main menu design, pause menus, settings navigation, and smooth transitions between menu states.
Guide 22 of 25
Screenshot
Step-by-Step Guide
Design menu states
Define menu states: Main, Settings, Play, Load, Credits. Each state has a unique panel with buttons.
Create menu panels
Build a Canvas with panels for each menu state. Only one panel is visible at a time. Use layout groups.
Add button navigation
Buttons transition between states. Play -> game scene, Settings -> settings panel, Back -> previous panel.
Implement pause menu
On Escape key, pause gameplay (timeScale = 0), show pause panel with Resume, Settings, Quit. Resume restores timeScale = 1.
Add menu transitions
Animate panel transitions with fade/slide. Use 0.2-0.3s transitions for smooth but responsive navigation.
Handle controller navigation
Support keyboard/gamepad: arrow keys move focus, Enter activates. Highlight the focused button.
FluxScript Example
Here is a complete FluxScript implementation for this guide:
menuState = "main"
menuHistory = []
isPaused = false
on start { showMenu("main") }
func showMenu(state) {
ui.hide("mainPanel")
ui.hide("settingsPanel")
ui.hide("playPanel")
ui.hide("pausePanel")
ui.show(state + "Panel")
ui.fadeIn(state + "Panel", 0.2)
if menuState != state menuHistory.push(menuState)
menuState = state
audio.play("menu_navigate")
}
func goBack() {
if menuHistory.length > 0 {
prev = menuHistory.pop()
menuState = prev
showMenu(prev)
}
}
on uiClick("btnPlay") { showMenu("play") }
on uiClick("btnSettings") { showMenu("settings") }
on uiClick("btnBack") { goBack() }
on input("escape") {
if gameRunning {
isPaused = !isPaused
if isPaused pauseGame() else resumeGame()
}
}
func pauseGame() {
gameRunning = false
world.setTimeScale(0)
ui.show("pausePanel")
ui.fadeIn("pausePanel", 0.15)
audio.play("pause")
audio.setVolume("bgm", 0.3)
}
func resumeGame() {
gameRunning = true
world.setTimeScale(1)
ui.hide("pausePanel")
audio.play("resume")
audio.setVolume("bgm", 0.7)
}
on uiClick("btnResume") { resumeGame() }
on uiClick("btnQuitToMenu") {
saveGame()
world.setTimeScale(1)
scene.load("main_menu")
}Node Graph Example
Prefer visual programming? Here is the equivalent Node Graph:
[On Start] --> [Show Menu: "main"]
[Function: showMenu] --> [Hide: all panels]
--> [Show: target panel + fade in 0.2s]
--> [Push: state to history] --> [Play: navigate sound]
[Function: goBack] --> [Pop: history] --> [Show: previous]
[On Input "escape"] --> [Branch: gameRunning]
+-- Toggle: isPaused
+-- True --> [pauseGame: timeScale=0, show pause]
+-- False --> [resumeGame: timeScale=1, hide pause]
[On UIClick "btnResume"] --> [resumeGame]
[On UIClick "btnQuitToMenu"] --> [Save + Load: main_menu]Optimization Tips
Keep your implementation fast and efficient with these optimization tips:
- Pool menu panels. Do not create/destroy panels on navigation — show/hide pre-created panels. Prevents GC spikes.
- Animate transitions with 0.2-0.3s fades. Instant panel swaps feel jarring; smooth fades feel polished.
- Support keyboard and gamepad navigation. Arrow keys move focus; Enter activates. Essential for accessibility.
- Lower music volume in pause menus. Players expect audio to dim when paused. Restore on resume.
Common Mistakes
Not pausing game time
Set world.setTimeScale(0) when pausing. Without it, enemies and physics continue while paused.
No back navigation history
Track menu history with a stack. Without it, Back always goes to main menu, even from nested sub-menus.
