As I understand, I can access a child node from my node tree in the following ways:

get_node("Foo")
$Foo

or by defining a variable at the top of my script:
@onready var foo = get_node("Foo")

all of these seem to work fine. Is there a difference as far as performance is concerned? Or is there another reason to choose one over the other (except for personal preference and readability, maybe)?

    The first two are identical, except that in the first case you can also compose the node path from multiple strings (e.g. "Foo/" + something).

    These two happen at the time when the respective function is executed. onready happens during the ready phase.

    Capella
    As far as I understand, the @onready variant makes sure that the search for a node is conducted after all the nodes in the scene have been loaded and ready in the scene tree, avoiding errors due to components not loaded yet at the time of the search.
    About the other two use cases, I am inclined to use the get_node() function, just because i can use it in a hierarchy search more comfortably than writing the whole path (or DagPath as it is called in Maya), which remains more flexible in case the parent changes relationships within the main node hierarchy.

    • Zini replied to this.

      AlexDonnie

      the @onready variant makes sure that the search for a node is conducted after all the nodes in the scene have been loaded and ready in the scene tree

      That is not entirely correct. A node reaches the ready phase after all of it children haven been readied. Siblings can still be unready and parents absolutely will be unready.

      Capella In general is a good idea to use onready variables, but for more complex scenes, I would advise you to build a custom search solution so you can search nodes on other parent scenes by demand or at startup and also not being dependent on the path itself, you will fell it necessary specially when working with complex UI, like, getting the path for a button, where you may need to change the path of it a lot.

      I use something like this :

      @onready var btn_finder:Utils.TNodeFinder = Utils.TNodeFinder.new( $".." )
      @onready var btn = btn_finder.find("Button1")

        Capella There isn't much difference in performance, I just benchmarked it. I made these three functions that return the names of the nodes:

        @onready var label = $VBoxContainer/HBoxContainer2/VBoxContainer/BestResultClassLabel
        
        func return_onready() -> String:
            return label.name
        
        func return_shorthand() -> String:
            return $VBoxContainer/HBoxContainer2/VBoxContainer/BestResultClassLabel.name
        
        func return_get_node() -> String:
            return get_node("VBoxContainer/HBoxContainer2/VBoxContainer/BestResultClassLabel").name

        Running those calls 50k times gives:

        • @onready takes 20470 microseconds.
        • The $Foo shorthand takes 26521 microseconds, which makes it 29.5% slower.
        • get_node() takes 27217 microseconds, which is 33% slower.

        Not surprising, really. $Foo is just shorthand for get_node("Foo") and if I had to guess it's just slightly faster because under the hood the compiler eliminates one function call and/or passing the string argument. I don't know, but it's just a tiny bit faster.

        Using an @onready variable is of course the fastest because you do the node lookup only once, when your script is ready, and not each function call.

        So, if you can and need to access a certain node multiple times then store it in a variable.

          Toxe
          Thanks. That was the information I was looking for. So it totally makes sense to store it in a variable if you need to access the node several times.

          award "Same-scene limitation¶
          A scene unique node can only be retrieved by a node inside the same scene. To demonstrate this limitation, consider this example Player scene that instances a Sword scene:"