How to call $Node.AnimatedSprite.play() with Node being a variable?

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

Hello.

I didn’t know how to put this in words, so the topic is strange.
I get the error “Attempt to call function ‘play’ in base ‘null instance’ on null instance.” What I want to do is to be able to play an animation of a specific node, without writing a specific line of code for this node. I want this one function to execute every possibility. At the moment I have three different chests, and the chestname returns a correct string, even chestnode.name returns a correct name. But I don’t know how to make the path to AnimatedSprite work…

extends Node

var within_range = false
var opened = false
const NAME = "Chest"
var chestname

func _input(event):
    if event.is_action_pressed("ui_accept") and within_range == true:
	    var chestnode = get_node(chestname)
	    $chestnode/AnimatedSprite.play("open")

func _on_PlayerRange_body_entered(body):
    chestname = body.name
    if NAME in chestname:
	    within_range = true
	    print(chestname)

You should split up your questions and ask them separately (or just edit this question to remove the YSort component and ask it again).

literalcitrus | 2018-02-14 01:46

:bust_in_silhouette: Reply From: literalcitrus

$NodeName is just a macro for get_node("NodeName"), so in your example your $chestnode/AnimatedSprite.play("open") line is the same as doing get_node("chestnode/AnimatedSprite").play("open") which is probably why it’s return a null reference, there’s no node literally called “chestnode”.

Once you’ve made a reference to a node (either through get_node() or the $ macro), you do not need to retrieve the node again to call functions on it. You can just use node_reference.function_call(). In your example, you’re specifically wanting to get a child node of chestnode, so there are a few ways of achieving this.

You can either use string concatenation in the first get_node() call like this:
get_node(chestname + "/AnimatedSprite").play("open")

You could also use the existing chestnode reference and make another get_node() call. It’s important to note that you can’t use the macro ($) in this case because the macro takes everything after it as a literal string, rather than looking at any variables.
chestnode.get_node("AnimatedSprite").play("open")

Personally, I would recommend the first in your current example, but switch to the second one if you end up doing multiple things with the chestnode reference.

Ah now I understand what I was doing wrong, thank you very much! This actually explains a lot! :smiley:

Sumerechny | 2018-02-14 01:54