ReferenceRect in Godot – Complete Guide

Welcome to an explorative journey into the world of Godot 4, where we’re going to unravel the mysteries and practical uses of the ReferenceRect class. For those venturing into the realm of UI design or simply wishing to gain an edge in creating more intuitive and visually aligned game interfaces, this tutorial promises a treasure trove of knowledge. Whether you’re a budding developer or a seasoned coder, join us as we dive deep into how ReferenceRect can enhance your game designing toolkit.

What is ReferenceRect?

The ReferenceRect class in Godot 4 is a unique tool tailored for designers and developers engaging in UI construction. It’s a non-intrusive guide, providing a clear visual representation of a control’s dimensions without affecting gameplay or user interaction. Think of it as a blueprint that aids in the precise placement of UI elements during the design phase.

What is it for?

Imagine you’re laying out the controls of your game’s HUD or aligning buttons on a menu screen. ReferenceRect acts as an on-screen ruler, giving you a visual boundary that ensures every element is precisely where it needs to be, fostering a consistent look across different screens and resolutions.

Why Should I Learn It?

Getting to grips with the ReferenceRect is not just about making your UI look good; it’s about understanding the underlying structure of your game’s visual aspects. This facilitates the development of a user interface that’s both functional and aesthetically pleasing, two crucial components for keeping players engaged and delivering a professional feel to your projects. Learning how to use ReferenceRect efficiently can be a stepping stone towards mastering UI design within the Godot environment.

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Setting Up a Basic ReferenceRect Node

To begin with, let’s set up a basic ReferenceRect node within the Godot editor. This will help us grasp how to create and position the ReferenceRect in the context of our UI.

var reference_rect = ReferenceRect.new()
add_child(reference_rect)
reference_rect.rect_min_size = Vector2(100, 50)
reference_rect.color = Color(1, 0, 0, 0.5) # Half-transparent red

In this example, we’ve created a new ReferenceRect instance and added it as a child to our current node. We’ve specified its minimum size to be 100 pixels in width and 50 pixels in height, and set its color to a half-transparent red for visibility.

Aligning UI Elements Using ReferenceRect

Now, let’s use ReferenceRect to align a button within our game’s UI. We’ll position the button relative to the ReferenceRect to ensure it’s exactly where we want it.

var button = Button.new()
reference_rect.add_child(button)
button.text = "Click Me!"
button.rect_min_size = Vector2(100, 50)
button.align = Button.ALIGN_CENTER
button.margin_top = reference_rect.rect_min_size.y / 2
button.margin_left = reference_rect.rect_min_size.x / 2

Here, we’ve added a button as a child of the ReferenceRect so it’s directly affected by the ReferenceRect’s position. By setting margins and alignment, we can center the button within the ReferenceRect.

Responding to Window Resize

It’s crucial to ensure that UI elements adapt to window resizing. Let’s explore how to use ReferenceRect to maintain the positioning of our UI elements during a window resize.

func _ready():
    get_viewport().connect("size_changed", self, "_on_window_resize")

func _on_window_resize():
    var viewport_size = get_viewport().size
    reference_rect.rect_min_size = viewport_size * 0.5 # Adjust to 50% of viewport

In this snippet, we connect the viewport’s size_changed signal to a custom function. Inside the function, we dynamically adjust the ReferenceRect’s size to always be half of the viewport, ensuring our UI scales with the window.

Creating Dynamic UI Layouts

Dynamic UI layouts are essential for a responsive design. Let’s use the ReferenceRect to create a layout that adjusts based on the number of buttons dynamically added to the screen.

var button_count = 4

func _ready():
    for i in range(button_count):
        var button = Button.new()
        reference_rect.add_child(button)
        button.text = "Button %d" % [i+1]
        button.rect_min_size = Vector2(100, 50)
        button.margin_left = (reference_rect.rect_min_size.x - button.rect_min_size.x) / 2
        button.margin_top = i * (button.rect_min_size.y + 10) # Add 10px spacing between buttons

In the above code, we dynamically generate four buttons, each one placed below the previous with a 10-pixel spacing. We calculate the margin_left property to center the buttons within the ReferenceRect.

By utilizing the ReferenceRect in these examples, you’ll be able to achieve a solid UI layout foundation. In the next part, we’ll explore more complex examples and tips for leveraging this class to its full potential in Godot 4.

As we continue to harness the power of Godot’s ReferenceRect, let’s delve into scenarios that often stump developers and where ReferenceRect can provide tangible solutions. By anchoring UI elements relative to the ReferenceRect, we create a flexible interface, capable of adjusting to various screen sizes and aspect ratios.

We’ll use Godot’s anchoring system to maintain the relative position of our UI elements, which, when combined with the ReferenceRect’s visual aid, allows for a resilient UI design:

var health_bar = TextureRect.new()
reference_rect.add_child(health_bar)
health_bar.texture = preload("res://health_bar.png")
health_bar.rect_min_size = Vector2(200, 20)
health_bar.anchor_left = 0.5
health_bar.anchor_top = 0.1
health_bar.margin_left = -100  # Half of the rect_min_size.x
health_bar.margin_top = 50

This health bar is centered horizontally by setting its left anchor to 0.5 and its left margin to half its width in the negative direction. The anchor_top and margin_top properties place it a fixed distance from the top of the ReferenceRect.

Next, let’s dynamically adjust the ReferenceRect’s margins to keep it centered, even as the aspect ratio changes. We’ll achieve this by updating the margins in the _process function, which runs every frame:

func _process(delta):
    var viewport_size = get_viewport().size
    reference_rect.margin_left = (viewport_size.x - reference_rect.rect_min_size.x) / 2
    reference_rect.margin_top = (viewport_size.y - reference_rect.rect_min_size.y) / 2

The ReferenceRect stays centered because we calculate its margins based on the viewport’s current size minus the ReferenceRect’s size, divided by two.

For games with varying resolutions or different player preferences, we want our UI elements to maintain their proportions. To do this, we’ll adjust the ReferenceRect size and the elements within it based on the viewport’s aspect ratio:

func _on_window_resize():
    var viewport_size = get_viewport().size
    var aspect_ratio = viewport_size.x / viewport_size.y
    reference_rect.rect_min_size = Vector2(viewport_size.x * 0.8, viewport_size.x * 0.8 / aspect_ratio)

This code adjusts the ReferenceRect width to 80% of the viewport width and the height according to the current aspect ratio. This ensures that the ReferenceRect and contained elements keep their proportions across different resolutions.

When creating a responsive UI, it’s crucial to deal with orientation changes, especially for mobile games. Below, we respond to orientation change and adjust the UI elements to fit appropriately:

var is_landscape = true  # A flag to check orientation
func _ready():
    # Initial setup based on current orientation
    adjust_ui_for_orientation(is_landscape)

func _on_window_resize():
    var viewport_size = get_viewport().size
    is_landscape = viewport_size.x > viewport_size.y
    adjust_ui_for_orientation(is_landscape)

func adjust_ui_for_orientation(landscape):
    if landscape:
        # Landscape specific UI setup
        reference_rect.rect_min_size.x = get_viewport().size.x * 0.5
    else:
        # Portrait specific UI setup
        reference_rect.rect_min_size.x = get_viewport().size.x

In this example, we define a flag to track the orientation state. We call a specific function to adjust the UI for each orientation when either the game starts or the orientation changes.

By combining Godot’s layout system with the ReferenceRect node, we ensure that our game’s interface is not only visually pleasing but also highly adaptable to a variety of devices and resolutions, providing a professional, seamless experience for all players.

To further solidify our understanding of leveraging the ReferenceRect for intricate UI designs, let’s create a responsive menu that accommodates various screen ratios and layouts. We’ll add text fields, labels, and arrange them around anchored points within our ReferenceRect. Not every code snippet requires a separate heading, but each aims to showcase a different aspect of UI design with ReferenceRect in Godot 4.

Firstly, let’s implement a text label within the ReferenceRect, ensuring it’s always positioned at the top left of the ReferenceRect, regardless of screen size:

var label = Label.new()
reference_rect.add_child(label)
label.text = "Player Name"
label.anchor_left = 0
label.anchor_top = 0
label.margin_left = 10
label.margin_top = 10

In this code, we anchor the label to the top left and add a margin of 10 pixels to give it some distance from the edges, maintaining a neat and consistent look across screen sizes.

Moving on, we’ll add a text field next to the label where users can input their player name. We want this text field to scale in width while maintaining its position relative to the label:

var text_field = LineEdit.new()
reference_rect.add_child(text_field)
text_field.placeholder_text = "Enter your name"
text_field.anchor_left = 0
text_field.anchor_top = 0
text_field.margin_left = label.rect_min_size.x + 20  # Position after the label
text_field.margin_top = 10
text_field.margin_right = reference_rect.rect_min_size.x - 10
text_field.clip_text = true

This code places the text field to the right of the label and allows it to expand to the full width of the ReferenceRect, minus a margin, adapting neatly to different screen sizes.

As we consider various UI elements, a responsive settings panel becomes necessary. Below, we create sliding controls for volume and ensure they remain centered vertically within the ReferenceRect:

var volume_slider = HSlider.new()
reference_rect.add_child(volume_slider)
volume_slider.anchor_left = 0.5
volume_slider.anchor_top = 0.5
volume_slider.margin_left = -150  # Center it with a negative half-width
volume_slider.margin_right = 150  # Use positive half-width for right margin
volume_slider.margin_top = -20   # Center it vertically with a negative half-height
volume_slider.margin_bottom = 20 # Use positive half-height for bottom margin

This slider is set to remain in the horizontal and vertical center of the ReferenceRect, allowing for a smooth and adaptive UI element that maintains its position and functionality.

To complete our settings menu, we need to ensure buttons, such as an ‘Apply’ or ‘Cancel’ button, are properly aligned at the bottom of the ReferenceRect:

var apply_button = Button.new()
reference_rect.add_child(apply_button)
apply_button.text = "Apply"
apply_button.anchor_bottom = 1.0
apply_button.margin_bottom = -10
apply_button.margin_left = reference_rect.rect_min_size.x * 0.25 - apply_button.rect_min_size.x / 2

var cancel_button = Button.new()
reference_rect.add_child(cancel_button)
cancel_button.text = "Cancel"
cancel_button.anchor_bottom = 1.0
cancel_button.margin_bottom = -10
cancel_button.margin_left = reference_rect.rect_min_size.x * 0.75 - cancel_button.rect_min_size.x / 2

With the anchor set to the bottom and a negative margin, both buttons are positioned at the bottom with evenly split horizontal space within the ReferenceRect, retaining their usability on any screen.

Lastly, for games that may have rotating or animated UI elements, ReferenceRect can be used as a pivot point. Here’s how you animate a Sprite node rotating around the center of a ReferenceRect:

var sprite = Sprite.new()
reference_rect.add_child(sprite)
sprite.texture = preload("res://icon.png")
sprite.centered = true  # Ensure the sprite is centered on its position
sprite.position = reference_rect.rect_min_size / 2  # Set the position to the center of the ReferenceRect

func _process(delta):
    sprite.rotation_degrees += 90 * delta  # Rotate the sprite 90 degrees per second

By placing the sprite at the center of the ReferenceRect and animating its rotation, we create engaging dynamic effects that maintain their centered position within the UI, regardless of external changes.

Through this exploration, we’ve shown how the ReferenceRect can serve as a fundamental node for Godot 4 UI development, providing a versatile foundation for adapting and anchoring UI elements across a myriad of game styles and devices.

Where to Go Next in Your Godot Game Development Journey

Mastering the ReferenceRect node in Godot 4 is just the beginning of your journey in crafting engaging and interactive game UIs. We at Zenva encourage you to continue exploring, experimenting, and expanding your game development skills. For those of you eager to deep dive into more complex projects and widen your Godot expertise, our Godot Game Development Mini-Degree is the perfect next step.

This comprehensive collection of courses is meticulously designed to transition you from a beginner to a proficient game developer who can create cross-platform games with ease. You’ll get the opportunity to engage with a plethora of topics ranging from 2D and 3D assets, GDScript, gameplay mechanics, to building full-fledged games for your portfolio. And the best part? Learning with Godot 4 means you’re working with a powerful, free, and open-source engine that enjoys strong community support!

Moreover, if you’re looking to broaden your horizons even further, take a look at our wide array of Godot courses. Each course is packed with engaging content and practical projects that cater to both novices and seasoned developers. By joining us at Zenva, you’re not just learning; you’re building a foundation for countless opportunities in the thriving game market.

Conclusion

Throughout this tutorial, you’ve unlocked the potential of the ReferenceRect in Godot 4, equipping yourself with the knowledge to craft robust and adaptable UIs for your games. Remember, the skills you’ve developed here are a springboard to creating more complex and engaging game experiences. But knowledge is a treasure whose pursuit is never complete, and there’s so much more to learn and discover.

So, let your curiosity guide you further – embrace the challenge, expand your capabilities, and join us on an unforgettable adventure in game development. With our Godot Game Development Mini-Degree, the gateway to mastering game creation is at your fingertips. Start your next chapter with Zenva today, and turn your game development dreams into reality!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.