Godot Version
4.4.1
Question
I am building a TowerDefense game and I would like some advice on how does the UI setup go usually. For my game I so far have one canvas layer called UI and below that I have a mix of a few different nodes like a control node for the pause menu, a panel container called HUD which stores the HUD, and another panel container which has the buildmenu. Now I was debating on whether I should store all of the code in the UI canvas layer and just create it like that or to add a script to all of the elements like HUD to hold some hud code like for the resources and such, BuildUI for the building and more. My general concern for this is that it would have a lot of extra connections like HUD sends to CanvasLayerUI then that to other node etc. I know that spliting the code is quite beneficial since I can clearly separate the functions a thing should do and it will do only that but in this case I have been a bit stumped. Any thoughts and advice are appreciated since I am still trying to learn the general flow of programing with Godot.
So, I would recommend all needed code be stored relative to each part of the UI that uses it.
You can then either have signals that connect to a func in the canvaslayer that connects to the other relavant code, or if you want to avoid signal then calling, you can use the common parent to connect all needed signals directly to the other UI.
Example.
Menu β signal for opening hud
CanvasLayer β connected signal at ready
Hud β recieves signal and does something
Also, depending on type of code you can control it from parent. I had an inventory system that I used the parent as the controler that initiated the code in the inventory, through input.
So it would be better to split the functions overall. Like for example the BuildUI to send a signal that Towerβs button was pressed to notify the UI and then the UI to send that to the BuildManager.
Basically making each component to be divided in their own respective roles
I donβt know your exact UI needs, but I would say itβd be more desireable to have each UI handle its own thing, rather than one monolith.
However, depending on hierarchy structure how you exactly do it would differ. If you have a UI bar with different towers you can build, that that would control everything up to point of actually initializing tower into the game.
Say when you click on valid location, when you click now it would send a signal that would communicate where it needs to insfantiate the tower into the game.
How you handle the data needed to do that depends on your structure and your needs.
The general principle is to break code up into segments that control something specific, and then for communication to call down and signal up or over. You can also use call/return to get needed data from children or other func.
It is difficult to give specific advice without knowing your games needs. You can always refactor later. I have refactored loads of code as my understa ding has grown. Starting with a working model for me is the most important, then if you break it you can learn why and how to improve it.
So, I would generally have a UI controller, with all different parts of UI contained under it with their specific code. These would then be engaged with via your controller.
For your example what is the node structure?
World
->UI
->-> BuildUI
->Build manager
Something like this?
Well I have it as
World
β UI
->-> HUD
->-> BuildUI
->-> PauseMenu
β Level
->-> Level specific nodes
β BuildManager
This is my general setup. And my whole UI code is found in the Canvas layer and the others just send push button signals to connect there.
Hi
Signals are a really useful tool in Godot. My advice is to save the components of your UI as scenes and use @export variables to set the variables of the component in the editor. Have signals that the parent node can connect to from the component. In this way you can reuse the component in other parts of your project or even reuse it in other projects. It is a bit more code but its more organized and easier to debug as the project grows in size and complexity.
Remember to add locale early on in your project even if you only support 1 language at first. Getting it implemented early on save a lot of time.
Use containers, margins, and anchors as it really helps with supporting multiple screen resolutions.
Create a base script for all your commonly used code for your UI and extend your UI from the base script. This can be used for any code in your project.
Create a class name for your scripts and use static typing as both are really useful and help with auto completion. Just note that autoloads will have a class name created automatically.
Enabling type hits (static typing) in Godot go to Editor β Editor Settings β Text Editor β Completion β Add Type Hints. I think it should be enabled by default since Godot 4.3 or 4.4.
Having all the code in one place can become messy as the project grows. It may be best to separate the code into multiple scripts. Each UI node should have a script that holds the functions for that UI node. The UI script should have a reference to its child nodes (HUD, BuildUI, PauseMenu). Call the functions of each UI component in the UI script and connect the signals to the UI script. That way HUD, BuildUI etc is responsible for their own functionality and the UI node is only responsible managing its child nodes.
The general idea is that the child nodes are responsible for their own code and functionality and the parent node manages the child nodes through signals and the functions created in the child nodes.
Thank you, I will try to make some changes now and to split up the functions between the different scenes in order to make a better flow of the communication.
1 Like