Godot 3: Centering a grid of evenly-spaced buttons on screen

In this tutorial: The scene structure and settings I used in the Godot 3 engine to achieve this amazing centered grid of evenly-spaced buttons. The buttons themselves are all instances of the same scene and are placed in the grid programmatically.

This is my “finished” result (pardon the placeholder assets). It’s a simple hero inventory page for an RPG. The buttons that make up the hero inventory are evenly spaced in a grid, and that grid is centered horizontally on the screen:

This guide will show you the code and the scene structure used to achieve this centered-grid-of-centered-buttons, but it assumes some familiarity with the Godot engine and will skip over some of the basics.

Scene hierarchy and container settings

This “Hero Page” is its own scene. This scene is named heroPage.tscn (and its script is in heroPage.gd). We’ll come back to its script at the end of the tutorial.  For now, we’re working in the scene’s hierarchy.

The parent-most node is a Node2D, and the important bits here for the centered grid of inventory items are:

  • a CenterContainer (which I renamed to centerContainer)
  • a GridContainer (which I renamed to grid)

(You could make this stuff programatically if you prefer but I like to see a certain amount of my UI in the viewport – at least the outlines of containers, where possible.)

I positioned my CenterContainer where I wanted it on the Y axis and gave it a width equal to that of my screen and left the rest alone.

Doesn’t look like much in the viewport yet – just a thin horizontal line.

That’s okay – the buttons themselves will bulk it out.

The next step is to adjust the grid’s settings. I changed the number of columns to 4 and under Custom Constants, I changed Vseparation and Hseparation to 24 (to put some space between each of the buttons).

The button instances

The square buttons are all instances of the same “itemButton” scene (that I made myself). That scene looks like this in the 2D viewport and scene hierarchy:

Unlike the grid or center container, I gave the button’s Control parent a size and a minimum size.

Generating the buttons with script

Finally, the code that adds the buttons to the grid is in the heroPage.gd file itself. This code goes in the _ready() method.

for i in range(heroEquipmentSlots.size()):
   slot = heroEquipmentSlots[i]

   var inventoryBtn = preload("res://menus/itemButton.tscn").instance()
   inventoryBtn._set_label(heroEquipmentSlotNames[i])
  
   #only set icon if the hero actually has an item in this slot
   #otherwise leave it empty
   if (global.selectedHero["equipment"][slot] != null):
      inventoryBtn._set_data(global.selectedHero["equipment"][slot])

   $centerContainer/grid.add_child(inventoryBtn)

I simplified some of the above code from my actual project for readability. The important parts are where it generates an instance of each inventory button and pushes the label and data into that instance, then adds the button to the grid.

The end result

The hero’s eight inventory slots are now in a grid and neatly centered. (I can’t say the same for the rest of the elements on this page yet, but it’s a start!)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.