UI visual and scaling help

Godot Version

v4.6.1.stable.official [14d19694e]

Question

My (relatively) massive solo project is progressing resonnably well. Still too slow for me to feel comfortable with the timeline I’ve given myself (for important reasons), but I am getting there.

I’m looking into how to integrate UI visuals to have something more professional looking. Problem is that I can’t find any tutorial that goes pass “Here is the basic Grey button/UI”.
I need a more complete tutorial that shows a professional end result.

I’m also concern about UI scaling. My project is base on 1 resolution and the UI is kinda fixed in place. I have yet to make a “UI scaling option” nor a “Resolution preset”. Any good/easy way to implement this in my active project?

Extra note: There is some HUD that show information, but it is very minimal.

A professional end result of what?

Did you read this already?

I did read about Multiple resolution. I’m also aware of Multiple Resolutions and Aspect Ratios demo project
The problem is I have trouble understanding when it is 90% text.

What I’m looking for is some complete tutorial that includes UI scaling AND Resolution scaling as “in-game options”. Preferably with some nice visual integration so it doesn’t look like a paint.jpeg menu (like I currently have)

I managed to find a very good video tutorial to help, but I’m encountering an issue (Most likely due to my own lack of experience with UI)

Whenever I change text size, the spacing I make to center everything properly ends up misaligned.
When I have simple buttons like my main menu, everything is fine since it 1 Vbox with 4 buttons. I just need to manipulate a few settings.

When I get to scenes that looks like this:


I get the feeling I’m complexifying things for no reason.

I’m currently in the “Make it good” phase, not yet to the “Make it pretty”.
So I don’t mind replugging buttons and updating scripts, but not redoing the whole thing from scrap.

EDIT: Don’t mind the very small Font size, it is “normal” since I,m exploring how to fix other things first.

I’ve struggled with UI scaling as well. My ‘solution’ is designing toward a targeted DPI (160) and then scaling everything at start-up based on the screen the app is running on.

var target_dpi := 160.0 # My development environment
var ui_scale := 1.0
var default_font_size := 16
var icon_size := Vector2(32, 32)

func _init_display():
	ui_scale = DisplayServer.screen_get_dpi() / target_dpi
	default_font_size = roundi(default_font_size * ui_scale)
	icon_size = (icon_size * ui_scale).round()
	# ...

I then have a couple helper classes. One iterates through the current Theme and updates everything that requires scaling (font sizes, borders, margins, etc.). The other generates appropriately sized icons from SVGs.

Also, I use anchors for all element positioning.

I’m intrigued, can you show me a more detailed example, with a simple scene or Images?
I’m a very visual learner.

I agree your SceneTree looks a little too complex for what it actually is.
I tried recreating your scene and this is what I ended up with, see how much more compact it is, even though the content is basically the same:

I think you even can’t have any less Nodes than that, I used absolutely the minimum amount that would be required to build this Scene without changing the content.

Here’s the code if you want to see how it was created and play around with it:

scene.tscn
[gd_scene format=3 uid="uid://cjxxgie2twvg3"]

[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8dbh4"]
content_margin_left = 20.0
content_margin_top = 10.0
content_margin_right = 20.0
content_margin_bottom = 10.0
bg_color = Color(0.1, 0.1, 0.1, 0.6)

[node name="Scene" type="CanvasLayer" unique_id=165001488]

[node name="PanelContainer" type="PanelContainer" parent="." unique_id=1864451740]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -250.0
offset_top = -150.0
offset_right = 250.0
offset_bottom = 150.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_8dbh4")

[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer" unique_id=922504678]
layout_mode = 2
theme_override_constants/separation = 10

[node name="Label" type="Label" parent="PanelContainer/VBoxContainer" unique_id=941342460]
layout_mode = 2
text = "HEADER"
horizontal_alignment = 1

[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer" unique_id=1756973123]
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/separation = 20

[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/HBoxContainer" unique_id=400435293]
layout_mode = 2
size_flags_horizontal = 3

[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer" unique_id=835785517]
layout_mode = 2
text = "Difficulty"
horizontal_alignment = 1

[node name="OptionButton" type="OptionButton" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer" unique_id=591731528]
layout_mode = 2
selected = 0
item_count = 3
popup/item_0/text = "Easy"
popup/item_0/id = 0
popup/item_1/text = "Medium"
popup/item_1/id = 1
popup/item_2/text = "Hard"
popup/item_2/id = 2

[node name="VBoxContainer2" type="VBoxContainer" parent="PanelContainer/VBoxContainer/HBoxContainer" unique_id=430748127]
layout_mode = 2
size_flags_horizontal = 3

[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer2" unique_id=1469127768]
layout_mode = 2
text = "Map option"
horizontal_alignment = 1

[node name="ItemList" type="ItemList" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer2" unique_id=1079605211]
layout_mode = 2
size_flags_vertical = 3
item_count = 3
item_0/text = "Map 1"
item_1/text = "Map 2"
item_2/text = "Map 3"

[node name="VBoxContainer3" type="VBoxContainer" parent="PanelContainer/VBoxContainer/HBoxContainer" unique_id=85151633]
layout_mode = 2
size_flags_horizontal = 3

[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer3" unique_id=203944271]
layout_mode = 2
text = "Recipe book"
horizontal_alignment = 1

[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer3" unique_id=505322206]
layout_mode = 2
text = "Flavor"

[node name="OptionButton" type="OptionButton" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer3" unique_id=710002909]
layout_mode = 2
selected = 0
item_count = 3
popup/item_0/text = "Sweet"
popup/item_0/id = 0
popup/item_1/text = "Sour"
popup/item_1/id = 1
popup/item_2/text = "Umami"
popup/item_2/id = 2

[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer3" unique_id=1264358163]
layout_mode = 2
text = "Planned menu"

[node name="OptionButton2" type="OptionButton" parent="PanelContainer/VBoxContainer/HBoxContainer/VBoxContainer3" unique_id=687728443]
layout_mode = 2
selected = 0
item_count = 3
popup/item_0/text = "Default"
popup/item_0/id = 0
popup/item_1/text = "Pizza"
popup/item_1/id = 1
popup/item_2/text = "Burger"
popup/item_2/id = 2

[node name="Button" type="Button" parent="PanelContainer/VBoxContainer" unique_id=784696369]
layout_mode = 2
text = "BEGIN COURSE"

[node name="Button2" type="Button" parent="PanelContainer/VBoxContainer" unique_id=20179077]
layout_mode = 2
text = "RETURN"

I think you need to learn how to properly use anchor presets, container sizing flags and V/HBoxContainer separation property in the theme.

2 Likes

Thank you for your help, I’ll explore your scene structure.

I do use anchor presets, container sizing flags and V/HBoxContainer separationin all of my scenes that needs buttons, cotainers and other controls

This one was my first attempt and is kind of a Legacy learning experience. Before I learned about CanvasLayer and other very important UI features.

I’m not saying that you’re not using them, but rather hinting that you should learn how to use them properly. From the Scene you showed I can deduct you may not understand them fully yet.

Hope you don’t get me wrong and will take this as an opportunity to grow. I’m looking forward to seeing your improvements soon :slight_smile: be sure to share it here!

2 Likes

how to use them properly

You are correct, I did misread. French brain read too fast sometime and ends up making up incorrect conclusion.

I’ll most likely share the first itterration of a more “complete” UI within the week, if UI visual and UI clutter fix are going well/fast enough :slight_smile:

3 Likes

My implementation for Multi-Resolution UI scaling isn’t very visual - just code. I am considering making an addon out of it - but the code isn’t ready for that yet, and I just don’t have the time (it’s working well enough for me).

Unless you are really interested full multi-res support, I would just use the project’s stretch mode settings (it you aren’t already). Then, you’ll only have to worry about getting one resolution looking good.

In Project → Project Settings…

1 Like

After following a quick tutorial, I’ve managed to figure out that I can also use Control picker to create different “Default size” depending on which controler I picked and added.
Basically, I assign 1 theme ressource the the Container, pick what controler and add what I want to affect.

Meaning I can have 1 “Master” theme for the font style and size, while still making “Sub theme” for more detailed modification. Could also use only 1 theme, but the options are there.

I decided to use* stretch mode to allow some smaller screen to still play without all the GUI ending behind each other. Planning to have some resolution option OR just able manual resizing while leaving the game playable.

P.S.: Ignore the weird viewport size. my screen seems to be not quite 1920x1080 (Despite what Windows says) It the only way I can control where the game goes on my screen if I want acces to Remote and other Editor setting while the game is running.

1 Like

That looks much better now, good job!

If you don’t need any more support for now in this area, mark some response as a solution to your problem, so that others know it has been resolved. You can always create a new topic in case you encounter new issues.