Correct way to pass variables down to a child scene

Godot Version

4.2.1

Question

I have a parent scene and a child scene. The parent is passing a variable to the child in the _ready() function:

Parent:

var parent_variable: String = "test"

func _ready() -> void:
	child.variable = parent_variable

The problem is that in the child _ready() function there is a method that needs that variable to work, but that function is called before the variable arrives from the parent, resulting in failure.

Child:

var variable: String

func _ready() -> void:
	function(variable)

What is the best practice in these situations?

I am not certain about best practices, but what you can do is:

  1. Access your parent by name using $. This is most certainly not best practice if your child is supposed to be reusable.
  2. If your child is added in code, use the _init function by overriding it.
  3. Worst practice would be using get_parent.

I have another idea but I don’t think if that will work and I don’t think it would be best practice. You could probably use @extern to enter the parent path from the parent scene to ensure reusability. I recommend using asserts to make sure the variable is set however to avoid unforeseen runtime issues.

1 Like

there are many ways to do it, and best practice depends on your code architecture.

one way to solve this is calling to child’s function in the parent’s _ready() function:

func _ready() -> void:
    child.function(parent_variable)

however, this isn’t very modular, and another but more verbose way to do it is notifying the child through a signal:

parent code:

signal is_ready
var parent_variable : String = "test"

func _ready() -> void:
    child.variable = parent_variable
    is_ready.emit()

child code:

var variable: String

func _ready() -> void:
    parent.is_ready.connect(_parent_ready)

func _parent_ready() -> void:
    function(variable)
2 Likes

I would not recommend accessing the parent from the child, for 2 reasons:

  1. nodes generally “own” and know about their children, but should not know about or rely on their parents
  2. as you’re seeing, the _ready() functions get called from the lowest point in the tree, traveling upwards (so at each node you can rely on its children already being ready). The parent’s property you’re trying to read might be available and ready to use, but since the parent’s _ready() hasn’t run yet, you shouldn’t count on that

@teivfik 's solution is a good one. I’ll add another example expanding on their first suggestion, because I believe there’s merit to the design that you use Signals to bubble messages up, and rely on method calls going down (so that the child continues to remain oblivious about its parent - the parent should already know about the existence and type of the child):

child:

private bool initialized;
private string vari = "Not Initialized"; // value is optional, but could help troubleshooting

public override void _Ready() {
    initialized = false; // redundant but illustrative
}

public void Initialize(string variValue) {
    vari = variValue;
    initialized = true;
}

// other methods can check `initialized` and fail/handle appropriately if `false`
// (IMO printing an error, but not throwing an exception, is the
// best practice here)

parent:

public string ChildValue { get; set; }

public override void _Ready() {
    child.Initialize(ChildValue);
}

(sorry not sorry about the C# instead of gdscript :sweat_smile:)

2 Likes

I’m lazy and use global variables.

That way any part of your code can access and adjust the variable.

1 Like

I also like global variables and access them with get/set. But when calling down to my children, then there are some good reads online. This site was actually pretty good at explaining things within godot.

https://kidscancode.org/godot_recipes/3.x/basics/node_communication/index.html

1 Like

In a post talking about best practices, I don’t believe it’s correct to encourage programmers to use global variables such as others have suggested.

Global variables should be used sparingly and only for properties or functions that architecturally could be used by all nodes in a scene.

And looking back, I made a mistake in my original post - as @emberlockgames has pointed out, it’s not good practice to access the parent from a child node, so my approach using signals isn’t the best, and child initialization should be done through a function called in the parent script.

2 Likes

There’s always a time and place to use global variables. They’re easy to use and easy to understand, especially when you want to use databases. Like when you create JSON files to store all your Dialog, Quests, Items, etc. Or when you decide to translate your game.

But like most things, “It depends”, is a very common answer.

My thought was that - for a beginner with a small project, global variables would be an easy way to get a project going.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.