How to properly reference a node?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By C:\Flavius

I have a scene made by only 20 labels and one generic node called “global”.
Global node will have a script that is autoloaded and also called global and will consist of a function and variables from the 20 labes that will be accesible by all the other scripts I’ll make.
What I want is to make text appear in the node that’s lower on the screen and then as that node’s text is updated, the previous text will appear in the node above it as a kind of history of all the text I printed.
For that I wanted to make the lower label say “Hello world!” when the program starts, using global script. Of course I could use that label (which is called CurrentLine cause the user will be able to write commands), use the _ready function of that label and tell it to print that but what I actually want is to make that script which will imitate the boot log of an OS, and it will push the text from line2 to line3 to line4 whenever a new line of text appears.

But I can never get the reference to any node correctly. With my last program I had the same problem but it was a lot simpler and didn’t really need to reference any node so much.
I first tried (naive me) with

var CurrentLine = get_node("CurrentLine")

and then in the _ready() function

CurrentLine.set_text("Hello World!")

It apparently cannot set_text to null base.
So I changed the “CurrentLine” with “res://Content/Scenes/Main.tscn/CurrentLine” but I had no luck so it didn’t work either.
Then I tried initializing a variable in global called CurrentLine, then create script for the CurrentLine label and in there

global.CurrentLine = get_node()

But that’s not working either. I even changed the () to (self) and (“CurrentLine”) but it doesn’t work either.
And I can’t seem to find anywhere on the internet a page where they tell you explicitly how to reference one node (CurrentLine) from another script (global) that doesn’t extend CurrentLine.

In my last program I could make every LineEdit change a variable in it’s own global script which stored those values to use them in a different scene.
But it wasn’t really referencing those LineEdit’s but the global script itself.
In this case I want the global script to keep track of the text in the CurrentLine (where the player will write commands) and push it to the above label, and the text in that label above, push it to the label about that one and so on and so forth until it reaches label20 where the screen ends and it just gets deleted. And also I want to create some sequences of text lines like the one sequence I said it would imitate boot logs from linux live CDs.
But I can’t do that if I can’t get a reference to each and every label so PLEASE HELLLLPPPPPPP!!!

:bust_in_silhouette: Reply From: Oen44

get_node takes NodePath as argument. If it’s returning null, then node can’t be found so NodePath is wrong or Node doesn’t exist.

And what would a correct example of a NodePath look like? Do I need to use the res://?
Where does the path of a node start? From the scene it is in? From res://? From the HDD it is in?

C:\Flavius | 2018-09-22 22:16

res:// is used for project files.
NodePath is for Nodes in scene, you have to specify path related to scene tree.

- Node2D
  - SomeContainer
    - Label

NodePath for Label is SomeContainer/Label, ignore Node2D if that’s your Root (first Node in tree).

Oen44 | 2018-09-22 22:19

What if my label is called “CurrentLine”? Is it’s NodePath still SomeContainer/Label or is it SomeContainer/CurrentLine? And what is that SomeContainer thing? This label is a child of the scene, I mean, it is not a child node of any other node.
I am already trying many combinations but it’s a pain in the neck cause it crashes every time and it takes some time to close it and change the line again.
Righ now I’m using

get_node("Main/Label").set_text(new_text)

But doesn’t work either so who cares.
I already tried using “Main/CurrentLine” so nope, no idea

C:\Flavius | 2018-09-22 22:26

I just used random names. If your node is named CurrentLine then use that name in NodePath.
Post a picture of your scene tree (where all nodes are present).

Oen44 | 2018-09-22 22:27

Okily dokily here’s a screenshot:

enter image description here

I called the scene main cause it’s the main scene. Then there are 20 labels. 20 is the highest up, and CurrentLine is at the bottom of the screen.
Sorry for taking so long, I didn’t know how to post a screenshot in here, and I had to post it on imgur first.

Edit: for some reason I can’t see the image so here’s the url Imgur: The magic of the Internet

C:\Flavius | 2018-09-22 22:40

Now it depends on which node is using that script, I’m guessing it’s global. Try using that get_root().get_node("CurrentLine")

Oen44 | 2018-09-22 22:46

Nonexisten function “get_root” in base “Label (CurrentLine.gd)”
What I wanted to do is to store the value of get_text of each label in string variables inside global, instead of dynamically reading and changing text in the script. Then make every label read those strings when they have to change their own text.
At this point I think I could use some kind of event to first make labels store their text and then change it.

It annoys me a lot I can never get the references right.

C:\Flavius | 2018-09-22 22:57

Ohh, thought get_root is equivalent to GetRoot() in C#.
CurrentLine.gd is used by global Node? Last thing I can think of is get_parent().get_node("CurrentLine"). I’m on my phone right now so not even able to test or something.

Oen44 | 2018-09-22 23:01

Apparently get_parent() is indeed a function in godot but the “CurrentLine” is not correct as it again tells me it can’t set_text to null base.
I think I can do it without referencing any node, only I will need to create a script for every label and use events to change their text.
I should also read more of the documentation, maybe I can find something that I didn’t see before

By the way, it’s already late in the night where I live so I’m gonna go home, thank you for your time!

C:\Flavius | 2018-09-22 23:13

Just got on PC, created test scene and here are the results:

#Scene Tree

- Node2D (Type: Node2D)
   - Global (Type: Node2D, Script: Global.gd)
   - History1 (Type: Label)
   - History2 (Type: Label)
   - History3 (Type: Label)
   - CurrentLine (Type: Label)

#Global.gd

extends Node2D

func _ready():
	var currentLine = get_parent().get_node("CurrentLine")
	currentLine.text = "Test"
	pass

And it worked.

Oen44 | 2018-09-23 10:05

There is definitely something wrong with my version of the software, I’ll try and update it and see if it works, but shouldn’t this work in any version?

Imgur: The magic of the Internet

After updating I’ll try again.

C:\Flavius | 2018-09-23 10:42

Node History2 doesn’t exist, look at your Tree.

Oen44 | 2018-09-23 10:43

It does, and after updating it still doesn’t work.

Imgur: The magic of the Internet

I have 20 labels, CurrentLine, and 19 history lines.

I think I can do this without referencing them but it’ll be quite inconvenient.

C:\Flavius | 2018-09-23 10:49

That should not be happening, which version of Godot are you using? Is it 3.0.6?

Oen44 | 2018-09-23 10:52

I was using 3.0.2, but I now installed 3.0.6 and it’s still happening.

C:\Flavius | 2018-09-23 11:15

I’m so sorry but that’s over me, maybe I’m missing something, can’t figure out why is that happening.

Oen44 | 2018-09-23 11:18

It’s okay, I’ll try the other way, and also I’ll ask godot for support.
Thanks a lot for your time!

C:\Flavius | 2018-09-23 11:20

:bust_in_silhouette: Reply From: luislodosm

For referencing nodes in the inspector:

export var path_to_my_node: NodePath
onready var my_node = get_node(path_to_my_node)
:bust_in_silhouette: Reply From: Surtarso

make a Globals.gd autoload and add:

var node_i_need_reference = null

than on the node you add:

func _ready():
    Globals.node_i_need_reference = self

That will work across scripts etc… inside the same script a simple

var my_node = $MyNode
my_node.method()
print("node name :", my_node.name)
my_node.visible = true

should work…

to add a child tho, you will need to reference the packedscene and instance it:

export var my_node:PackedScene ##drag scene to properties window
instance_of_node = my_node.instance()
add_child(instance_of_node)