The Godot Q&A is currently undergoing maintenance!

Your ability to ask and answer questions is temporarily disabled. You can browse existing threads in read-only mode.

We are working on bringing this community platform back to its full functionality, stay tuned for updates. | Twitter

0 votes

I'm trying to implement a component architecture for scripts for my project. I'd like for each scene to have just one script at its root that creates each script (behavior) and passes the necessary node paths (resources). Example:

extends Node

export(NodePath) var resource_node_path

func _ready():

The behavior script then has access to whatever resource nodes it needs; agnostic of the scene's structure:

extends Node

var resource_node

func _init(resource_node_path):
    resource_node = get_node(resource_node_path)

# Perform operations using resource_node

The issue is that get_node() must be called after the node has entered the tree, as in, from_ready() and not _init(). So, how do I resolve this while still being able to pass arguments through new()? I know I could just store the path in a class variable, but I'd rather not have this kind of temporary value cluttering the namespace. Alternatively, is there a better approach to reusing generic behavior scripts?

in Engine by (12 points)
retagged by

1 Answer

0 votes

You can do everything on _ready or _enter_tree, the architecture sounds a bit strange if a node needs to access the tree when is outside of it.

There are many other ways to do that like using groups or a specific autoloaded script or scene that takes care of organizing and giving a list of required resources to new nodes as they enter the tree (using notifications, signals).

ps: there is no class/static variables in Godot, only methods.

by (7,890 points)

Well no, the node is expected to access the tree once it has entered. The question is how to wait until that time to call get_node(). I could create an autoloaded script that holds a list to resources, but that seems messy, and defeats the organization of the tree and self-contained scenes.

I guess I meant instance variables.

A manager looks messy on the usual way (real singletons) but on Godot are just scenes with special behaviour and location on the tree, you can have many for different uses, like managing connections, pauses, saves and other top level stuff, if well organized (with groups, notifications, etc.), the self-contained approach should not be affected by those utility scenes, on the contrary, that will prevent it because depending on external nodes breaks that containment directly.

The time to call get_node is from _enter_tree and until _exit_tree, on _ready the Node/scene should be fully initialized in the tree so is usually safe to use it there (normally there is no need to process nodes before ready).

If you want to postpone the call (you may need a node that is not -yet - on the tree), call_deferred should help, to assign to a variable do call_deferred on a function that process the initialization part that depends on the get_node (maybe with hasnode>getnode and call deferred again if fail).

Adding all to a group and letting something else notify all of them for a special set-up (notify_group/call_group) may be cleaner IMHO.

More or less like the answer of avencherus.

Ah, I guess I didn't realize autoload could be used on an entire scene. That's helpful, thank you!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.