NodePath & get_node - get reference instead of path in editor

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By vtepe
:warning: Old Version Published before Godot 3 was released.
export(NodePath) var n     # assigned in editor - cool stuff
func _ready():
    n = get_node(n)        # cause nothing better to do in life

My guess is it’s over 90% of uses of NodePath… is there a way to get the node and keep it in one line? :slight_smile:

:bust_in_silhouette: Reply From: avencherus

Do you mean something like?

tool
extends Node2D

export (NodePath) var path setget set_path
var node_reference
    
func set_path(val):
	path = val
	node_reference = get_node(val)

Thanks for pointing me into tools but it’s even more work this way i think.

Would a tool iterating over all children and linking references in editor work? I need them linked in-game…

vtepe | 2017-04-08 10:14

What are you trying to accomplish?

I assumed you wanted tool mode, since you’re doing things with export vars, and those are accessed in the editor.

avencherus | 2017-04-08 10:16

Trying to pick a node via editor, but not having to type “get_node()” for every export i use. Looking for “once and for all” solution.

This is what i googled on this so far…
dfaction.net/using-reflection-in-gdscript-to-resolve-nodepaths

vtepe | 2017-04-08 11:27

Actually discovered that even calling get_node() on provided NodePath creates problems on ready when one node needs nodes in another node that gets ready later.

Abandoning "export(NodePath)"s for now. Would be great if it worked though.

vtepe | 2017-04-08 12:07

Using just var a = getnode(“path”) doesn’t work either as it demands to be onready in my case. Next solution: another node on the bottom of the list to connect other nodes and call their init functions… which can’t be “_ready” now.

vtepe | 2017-04-08 12:36

Ok, my results might’ve been obscured by missing “_” in front of “ready” in one place…

vtepe | 2017-04-08 14:46

It’s hard to say what you’re working on there.

If you’re having some issues with timing, you can use call_deferred to delay things a frame.

That can get kind of messy, alternatively you can try and create a central piece of logic that executes at the root node. When that one is ready you can be assured all child nodes are ready as well. Since ready works backwards up the tree.

Another thing you have to be mindful of with export variables in tool mode, is that when the scene initializes, the editor will take the saved value for that variable (from the scene file), and set it with the setter function. This will also execute any code you have there. So if you have code that depends on the state being ready, you will run into an error, because this code will execute at initialization.

You can wrap a setter like I have below, if you need to prevent conditional code from running in tool mode:

# For things that need to be in the tree
func set_export_var(val):
	my_export_var = val

	if(is_inside_tree()):
		# Do stuff

# For things that need to be ready
onready var is_ready = true

func set_export_var = val
	my_export_var = val

	if(is_ready):
		# Do stuff

avencherus | 2017-04-08 23:35

Thanks for the info, i was missing some of this :slight_smile:

Was trying to organise everything a bit better and tried some approaches and exports. Settled on a solution of parent node linking child nodes with each other. Some of them need others on their ready function and in general they need others while processing. Changed ready to custom defined lateReady wherever there was an error which is executed by parent after other nodes are connected. Seems to be working so far.

vtepe | 2017-04-09 00:04

You’re welcome. I’ve found in my work with tool mode, relying specifically on the init, enter, ready, exit, can be limiting. It’s best to do what you’re saying, and create a custom method of your own, and have it called only when you know the timing and conditions you need are met.

In the editing process, you’re not likely to notice a few lost frames on loading, if something has to wait to make sure the scene tree is in the state you want it to be in.

avencherus | 2017-04-09 00:16

:bust_in_silhouette: Reply From: Shishir Tandale

This is an old question, but this is what I’ve been doing in case anyone finds it useful.

export(NodePath) var node_path
onready var node_ref = get_node(node_path)

This way, you don’t need a _ready method if you won’t be using it for something else.

:bust_in_silhouette: Reply From: samildeli

I was trying to find out how to do this in Godot 4 and came across this question. It is old but no answer has a one-line solution, so here it is:

export(NodePath) onready var n = get_node(n)  # You can use type casting for code completion

Thank a ton, this has been so annoying. I hadn’t figured out this oneliner.

Snooze | 2022-04-25 22:09