Finding node problem

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

Hello everyone.
I know that my question is probably very stupid, but I can’t figure out what the problem is. (maybe there is no problem. and I just don’t have enough knowledge)
The project tree is very simple:
Node2D(named:MainScene)

  • TileMap
    • KinematicBody2D
      • CollisionShape2D
      • Sprite
        • Panel
          • Label

In the KinematicBody2D node, a script with simple control and variable speed.

extends KinematicBody2D
var speed = 70

func _ready():
pass #

func _process(delta):

var velocity = Vector2()
if Input.is_action_pressed("up"):
	velocity.y -= speed
if Input.is_action_pressed("down"):
	velocity.y += speed
if Input.is_action_pressed("left"):
	get_node("Sprite").flip_h = true
	velocity.x -= speed
if Input.is_action_pressed("right"):
	get_node("Sprite").flip_h = false
	velocity.x += speed
if Input.is_key_pressed(KEY_SHIFT):
	speed = 120
else:
	speed = 70
	
move_and_slide(velocity)

position.x = clamp(position.x, 5, 335)
position.y = clamp(position.y, 0, 330)

In the Label node, a simple script that should show the value of the speed variable from the script in KinematicBody2D.
And here lies my problem.
If I try to access the KinematicBody2D node to get the value of a variable velocity in $KinematicBody2D.speed (auto-complete, and there have to print the manual), when you run the project I receive an error “Invalid get index ‘speed’ (on base: ‘null instace’)”
If you are applying through get_node(), then the autocomplete suggests “.”, what’s not working.

The only working way I could find:

text = "speed: " + String(get_parent().get_parent().get_node("KinematicBody2D").speed)

It seems to me that I am missing some simple way to indicate the path to another node.
Or is that exactly how it should work?

:bust_in_silhouette: Reply From: ramazan

get_parent().get_parent().get_parent().get_node(“Node-name”).speed

or

get_owner().get_node(“Node-name”).speed

Thanks!

get_owner().get_node("Node-name").speed

also work fine to me.

Viskirson | 2022-01-22 07:02

:bust_in_silhouette: Reply From: chesse

Hello Viskirson,

you are using 2 get_parent(), that brings you up to Sprite and Sprite ist not a parent of KinematicBody2D. You have to use 4 get_parents() to get to TitleMap where you can find KinematicBody2D as a child

text = "speed: " + String(get_parent().get_parent().get_parent().get_parent().get_node("KinematicBody2D").speed)

or try

text = "speed: " + String(find_parent("KinematicBody2D").speed)

Thanks! find_parent("KinematicBody2D"work fine for me.

Viskirson | 2022-01-22 06:53

:bust_in_silhouette: Reply From: DaddyMonster

It’s always the questions where the person comes across as genuine and/or humble where everyone steams in and debates what’s the absolutely optimal solution to the nth degree. :slight_smile:

Ok, drop this whole get_parent().get_parent().get_node("Fart") malarky. get_node("../../Fart") means the same thing. It’s just more concise. So add ../ every time you want to go up one in the tree with get_node and you’re golden.

So, to reference the KB2D from the Label, it’s get_node("../../../../") (assuming these are all parents of each other, I’m interpreting the number of dashes as not meaning anything)

Thanks for the reply!

get_node("../../../../") 

it also works fine, as does “find_parent” from the answer above.
It’s a bit strange for me that there is no autofill of the path while writing the script. But it seems to be the norm.

I will use both options.

Viskirson | 2022-01-22 06:58

Well, it can’t autofill because it’s just a string. Getting slightly more advanced, there is the data type / object NodePath. If you put:

export var my_node : NodePath

Save this, click on the node and take a look at your inspector on the right and you’ll see a my_node field which you can click on to pick out the node you want to reference from the tree. This is convenient, saves you working out the path in your head but it also has a huge advantage:

If you use get_node("../MyNode")and then you move MyNode, this will crash as Godot can no longer find it. If you move the node using NodePath as above then Godot will handle this and it won’t crash so it’s less brittle and more robust.

There is also separation of concerns and dependencies to consider but that’s a huge topic and beyond the scope of this.

DaddyMonster | 2022-01-22 09:45

It’s amazing. Thanks so much for the detailed explanation!

Viskirson | 2022-01-22 16:37