Five Tips for Better Menus in Godot

Five Tips for Better Menus in Godot

1. Menu Manager

When I firsted started making games I inevitably came across wanting to make menus. A start menu, a settings menu, save, and load menus, etc. I would just add them in wherever it was needed and soon became super messy. In a small game it was manageable, but in a larger game it became a nightmare.

After learning a little about Godot and Global scripts or scenes, having a singleton Menu Manager would be a great place to start.

  • A menu manager that is a singleton that can be called from anywhere in the game
  • Build all the menus under this in one place
  • Keep menus in the Global space so I don't have to change scenes

By doing it this way I can easily manage what menu is showing and hide other menus. I liked how some games would keep the running scene going in the background and just swap out menus on top of it. Keeping the game running with sound also.

Documentation:

https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html

2. Menu Stack

Now that I have a Menu Manager and all menus are under it, I needed a way to easily go back and forth between menus. At first I kept a current menu variable and a previous menu variable.

An example would be on the Main Menu the player would push the Settings button and go into the Setting Menu. That menu would have a back button and I could look up the previous menu and go back to it. That way any back button would work the same and I wouldn't have to hard code in what menus go to what other menus.

Now the thing that broke my approach to this was from the Settings Menu I have a credits button that goes to the Credits Menu. So now I am three menus deep. How could I know what menu the back button wanted to go back to if I just have one previous menu variable?

A more elegant way is to use a stack.

https://en.wikipedia.org/wiki/Stack_(abstract_data_type)

A stack is basically an array of items that you can push to and pop from. Thinking of a stack of cards, you can add (push) a card to the top of the stack and remove (pop) the top card.

A way to go back and forth between menus in an elegant way. From anywhere to go into menus that have depth, and then get back out of it.

Now my back button can be 100 menus deep and still know how to get back to the top level menu.

Of course if you have a simple game with only a few menus then making something like this might be too complex.

Sample Code:

extends Node

@export var default_menu: String = "MainMenu"
@export var default_start_time: float = 0.0

func _ready() -> void:
	for child in get_children():
		if child is Menu:
			menus[child.name] = child
	if default_menu:
		await get_tree().create_timer(default_start_time).timeout
		push(default_menu)

func push(menu_name: String):
	if menu_stack.size() > 0:
		await transition_away_out(menu_stack.back())
	menu_stack.append(menu_name)
	await transition_in(menu_name)

func pop():
	var prev_menu_size = menu_stack.size()
	var menu_name = menu_stack.pop_back()
	await transition_out(menu_name)
	if prev_menu_size > 1:
		await transition_away_in(menu_stack.back())

3. Menu Animations

You can see if my code example above. I wanted 4 different animations for my menus.

Sure I could have just shown and hidden the menus, but I think having animations is probably the mest tip on this list to make the menus look better.

  • Transition In - This means going to the menu for the first time
  • Transition Out - This means transitioning out of the menu
  • Transition Away In - This means going down to a lower menu
  • Transition Away Out - This means going back up to a higher menu

Here are some more tips on making animations for menus:

  • Keep the animation simple.
  • Sometimes you want to animate a bunch of different things, which can look good, but is a nightmare to handle animations. What if you change something, then the animation needs to change.
  • Putting everything in a container makes it easy to animate the one container instead of every little thing

You can make animations of all shapes and sizes. Do it how you want to do it, but keeping it simple and animation the top level container is the best way to go.

4. Organize Menus Into Containers

When I first started making menus I would add the UI elements directly to the Canvas Layer and position it in Layout section. I would personally go to each Node and position it. Then in the animation I would animate every little thing. If something changed I would have to redo the animation.

Using containers changed my life in such a way that is indescribable.

Margin Container

https://docs.godotengine.org/en/stable/classes/class_margincontainer.html

The first container I use is the Margin Container. This is great since it keeps the same margin on the Nodes inside and makes everything line up consistently.

VBoxContainer

https://docs.godotengine.org/en/stable/classes/class_vboxcontainer.html

The VBoxContainer is great for vertical alignment. I can just add my Nodes to the container and it will keep them all aligned vertically.

I did have an issue where I wanted to keep the buttons on the bottom of my menu and have the title and description at the top.

I figured out if you set the container to Fill and Expand it will grow to fit the size of the container.

HBoxContainer

https://docs.godotengine.org/en/stable/classes/class_hboxcontainer.html

The HBoxContainer is great for horizontal alignment. Now I wanted to have a title and then in icon on the same line for a settings button. The Horizontal Box Container is great for this.

Panel

The panel is like a container in that it can contain other nodes. But it is a container that has a background color or a texture. You can setup a theme for it to make it look like a different color or texture.

I use a combination of all of these to make consistent looking menus.

5. Themes

The last tip is for themes. I wanted to make a bunch of different colors for my buttons since the game was a balloon popping game. However when I first made buttons I went into each button and made Theme Overrides. This was tedious and was difficult to manage each one of my buttons.

Theme Type Variations came in to save the day.

https://docs.godotengine.org/en/stable/tutorials/ui/gui_theme_type_variations.html

Theme type variations are a way to keep the default theme with colors and fonts the same but then have variations on the UI controls if needed.

So you just go in and create a variation of the Control Node you want. For example I made a Red, Green, Blue, button variations.

Then when I create a normal button, under the theme section, I can select the variation I want making it super simple.

This is a great way to keep the UI looking consistent and then just change the colors when needed.

Links


More Articles


Newsletter

Stay up to date with the latest articles, tutorials, and news.