Godot Version
4.2.2.stable - Windows 11 - GDScript
Question
First, some context.
I come from Unity, where in every component you have an Awake() and a Start() function. You can not normally know in which order each Awake or each Start function is executed. What you DO know is that first all Awake functions are run, then all Start functions.
This is what allows me to basically have each gameobject (would be node in this case) initialize itself and its references on Awake(), and then call methods on other gameobjects on Start().
With that said, after some investigation I have concluded that this workflow is basically not the same in Godot. Also, I learned that a root node _ready is only called when al its children have already been initialized. So, in other words, the _ready function is called from children to parent.
So, this is my problem. I want to see if the solution Im trying to do makes sense, or if it would be best to refactor and solve it in another way. Keep in mind this is a miniscule test example im doing and not some big project.
Node Structure of relevance:
- Game (Root Scene)
- Player (Scene)
- Gun (Scene)
- GunUICanvas
- BulletsLabel
- Player (Scene)
BulletsLabel is a Label that shows “Ammo: currentAmmo/totalAmmo”.
I want to do the following:
- When gun.gd initializes, it calls bullets_changed(bulletsAmmount) signal.
- When bullets_label.gd initializes, it listens to Gun.bullets_changed signal on _gun_bullets_changed(amoun) method.
- When _gun_bullets_changed is called, its text value gets updated.
When starting the game:
Expected behaviour:
- First, gun calls bullets_changed as a “setup call” (so that the label can get its start value)
- Second, label updates its value. This script does not store totalAmmo nor currentAmmo, this is stored on gun.gd script.
Actual behaviour:
As nodes are initialized from children to parent, Gun is initialized before BulletsLabel. So when BulletsLabelstarts listening to the signal, the first call has already been made before by Gun, so it doesnt get that initial call, only calls after that.
In summary, my questions are:
- How can I control de order of execution of _start if possible?
- If the previous answer is I cant, then how can I make sure (with a manual approach or something) that I have to instances of “startup” of each script (similar to unity). First, an instance where each script starts up itself and gets any references it needs, then a second step where each reference or signal can be called, making sure every other node has also been initialized and is correctly listening.
I hope I could make myself understood. Here is a screenshot of my hierarchy, and snippets of the relevant code that was mentioned:
gun.gd
extends Area2D
signal bullets_changed(bulletsAmount)
var maxBullets = 10
var bullets = maxBullets
func _ready():
print("gun._ready")
resetBullets()
... Some more code ...
func resetBullets():
bullets = maxBullets
bullets_changed.emit(bullets)
bullets_label.gd
extends Label
@onready var gun : Node2D = get_tree().get_first_node_in_group("gun")
var totalBullets = 0
func _ready():
print("bullets_label._ready")
gun.bullets_changed.connect(_gun_bullets_changed)
func _gun_bullets_changed(newBullets):
if totalBullets == 0:
totalBullets = newBullets
text = "Ammo: " + str(newBullets) + "/10"