0
\$\begingroup\$

How to get nested child node without using full path? I tried with just node name, it doesn't work.

The script is on top level so the path is quite long:

dialogText = GetNodeOrNull<RichTextLabel>("VBoxContainer/Panel/MarginContainer/DialogContainer/DialogTextWrapper/DialogText");

(Question originally posed on Discord and copied here.)

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

The simplest way is Node.find_child(), but that does a search each time it's called which can be slow.* When you're done prototyping, you'll want to change to another method.

You could do a Unique Name.

Or an @export in gdscript or C#.


* And by slow, I mean find_child() can be so slow that the docs warn about using it:

Note: As this method walks through all the descendants of the node, it is the slowest way to get a reference to another node. Whenever possible, consider using get_node with unique names instead (see unique_name_in_owner), or caching the node references into variable.

\$\endgroup\$
0
\$\begingroup\$

get_node(NodePath) fetches a node & can use the NodePath can be either a relative path (from the current node) or absolute. The relative path is typically shorter. When used as a literal you can further shorten the expression to $NodePath.

So with this Player scene:

enter image description here

And this PlayerGun scene:

enter image description here

Then in order to access the somewhat deeply nested Muzzle node from within my script for Player I would do this in 3.x:

onready var muzzle = $Sprite/PlayerGun/Sprite/Muzzle

or this in 4.x:

@onready var muzzle = $Sprite/PlayerGun/Sprite/Muzzle

Because I'm using a relative path, I don't need the full / absolute path. As as a bonus, the absolute path could possible change, but as long as I don't change the relative relationship between Player and Muzzle nothing breaks.

get_node() is more performant than find_node(). find_node() has to do a pattern matching search for its target whereas get_node() uses a hash map to children (which is also how unique scene nodes work).

\$\endgroup\$
5
  • \$\begingroup\$ I'm inferring the performance difference between get & find based on their definitions. If someone has a solid source that confirms or refutes my performance claim, please let me know or just add an edit. \$\endgroup\$
    – Pikalek
    Oct 1 at 1:25
  • 1
    \$\begingroup\$ The method get_node would get nodes by name from a hash map of the children, this is also how unique scene nodes work. And, yes, find_node will do pattern matching. I could not find a direct performance comparison. \$\endgroup\$
    – Theraot
    Oct 1 at 4:03
  • 2
    \$\begingroup\$ What I can tell you is that for Godot 4 find_node was removed to avoid misuse due to bad performance, then Scene Unique Nodes were added as a direct alternative, the reason being that people were using find_node to get nodes to prevent the code from breaking from changes in the scene tree. Although some argued that the performance wasn't a problem (you get reference once during initialization and reuse it) or that you should update the code when you change the scene tree. Ultimately find_node was restored (which eases porting from Godot 3 to 4) and subsequently renamed to find_child. \$\endgroup\$
    – Theraot
    Oct 1 at 4:09
  • \$\begingroup\$ @Pikalek: "Because I'm using a relative path, I don't need the full / absolute path." But the script is on the root node, so the relative path is just as long as the absolute path. \$\endgroup\$
    – idbrii
    Oct 3 at 17:10
  • \$\begingroup\$ @idbrii True however the question didn't specify a root node requirement & near the the beginning of my answer, I did qualify it with "relative path is typically shorter". That aside, the other advantages presented still stand. \$\endgroup\$
    – Pikalek
    Oct 3 at 19:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .