As I'm learning Godot, one area I keep falling down on and can't help feeling I'm doing something horribly wrong is when it comes to referencing a node by its path or calling a script function inside a script via the node's path. When I then inevitably rejig the order of my nodes after making a cosmetic change, or for whatever reason, I need to go through my script changing all the paths wherever they're referenced. This seems like terribly inefficient way of doing things and could easily result in missing a fix.

Is there a better way of doing this which I'm missing entirely? I changed to assigning a path to a variable so I only need to change it once at the top of the script but it still feels cumbersome. I also messed about setting up an init function that would run through an array of all my paths, checking they were valid so at least I could catch any mistakes on launch. But that felt like overkill.

Is there a "correct" way to do this?

Thanks that was an interesting read. I think what'll work for me from all that is using:

var rootToSomeNode = find_node("SomeNode")

Doing so right at the start and then storing that value in a variable so I only need to call that once.

That way I can mess about with the node tree as much as I like assuming I don't rename the node.

You may have already read this but some good bits of info here: https://kidscancode.org/godot_recipes/basics/getting_nodes/

I guess to a degree find_node vs relative path is down to personal preference. Do you prefer ensuring unique node names and never changing them, or do you prefer enforcing parent/child hierarchies and not moving children.

Personally, I try to ensure wherever possible that parent nodes control their children and all paths are then relative (i.e $parent/child or if absolutely necessary get_parent() when required). That way I can move the parent node and all children come with it without any paths needing updating. This approach also makes parent nodes reusable in other projects/scenes if exported/imported.

If I needed to just move a random child node but still have the Parent script reference it or vice versa... well I probably did something wrong in my design and would cause me to rethink what I am doing and ensure my scene tree is still consistent. Similarly, If a node needs to interact with another node in a completely different part of the tree, I would either use signals or a singleton instead to manage it I expect.

I don't really see this as a Godot bug necessarily, as imagine this would be true in any language when interfacing with a file structure or creating modules. While traversing up and down the scene tree is laborious I admit, I kinda assumed early on you weren't really supposed to. Wherever possible relative paths are you friend, and if you feel you need to hardcode a path, you might want to double-check if this is the only course of action available.

The main time this has become an issue for me is when I've written the script and then later want to adjust the layout for the scene, so I end up dropping a new container in, or rearrange the order of that scene's children altogether. So then any reference to a node becomes invalid and needs updating. As I'm still earning Godot this can happen a lot as I learn better ways to lay things out. I'm not sure I could manage to never change the nodes in a tree. That would seem quite restrictive to presume I'm going to get the correct node layout the first time.

So using find_node the first time the script runs is always going to bypass that issue for me. I can rearrange the tree however I want.

I don't really see this as a Godot bug necessarily, as imagine this would be true in any language when interfacing with a file structure or creating modules.

That's true. Maybe it's conspicuous in Godot because it's so easy to rearrange nodes in the scene tree. If you're using a language where the structure has to be defined by class definitions in text files, there's more motivation to get it right the first time.

I stick to using onready vars to reference component scene node of any 'module' scene I create. I think of them as my friends because then if a script associated elsewhere in the tree needs to interact with those component nodes, it does so through that script property, where the module scene instance is assigned by whatever method seems appropriate (NodePath for editor settable fields as an example) so Node (Fred as a Person) Node (Hand) * Node (Foot)

` Fred onready var hand = $Hand onready var foot = $Foot

... SomethingElse

var person = get_subject() # get fred person.hand.shake(other_person) `

If I expect even more variability I would use a method (function) to interact with the target node instead to abstract away from any node layout in the target.

Generally I will use "dependency injection" in other cases, say if I have a rig scene responsible to playing a "puppet" scene. So Rig controls Doll and this control is established by invoking a Rig function "control_doll(D:Spatial)" or something like that.

The thing to remember is scene tree and godot itself takes a strategy of functionality through composition. It is a bit different than composition by subclassing.

In general, the parent nodes should control the children, in which case (in an ideal world) you should never need the root node or to call up in the hierarchy. It's not a perfect world, and many times you will find need to access other nodes when you are making games. This is almost unavoidable, but can be done.

One way is to use (or abuse) groups. If you put some main important objects in a group by themselves (definitely the Player could be a good choice here) then you can use get_nodes_in_group() and you know the first result is always the one you want. Kind of a hack, but it works.

Another way is to use an auto load script, Singleton, to store the node paths of important objects. This way you only have to type them once, and all other objects can query for the Player or whatever, and it works and limits the amount of modification you have to do if you change the tree structure (only update the path in one location).

Finally, you can use an auto load script again, but have the individual classes class objects register themselves. The objects only need to know about the Singleton, and on initializing, they send their path to the global script. Then you can rearrange freely and it should all work, but I never tried this personally.

Also, using Signals will help reduce the coupling to hard-coded paths, and can be used in all these solutions to further reduce what the classes know about each other. So in the Singleton, you can wire up all the signals (events) relevant to the game, and then allow that one script to dispatch to the correct object. Not perfect, but this means that that only one script in the whole game has to have any paths (and these can be dynamic) but it's also a bit more complex and probably considered bad design.

I often try to use a combination of signals and exported Nodepaths, but the problem that can (and has) occur is the code becomes a bit of a mess with nodes all connected this way and that. It also can be a little annoying to setup all the editor Nodepaths for each node. All of that said, it’s often the method I use simply because for me, I have found it works with my design.

I think there isn’t a perfect solution that works for all projects or all developers and programming/design styles, so I’d recommend trying different solutions and seeing which works best for you and your projects :)

2 years later