get_current_node() returning nothing (not even null)

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

I’m attempting to have it so that the player switches between two different animation states using an animation tree upon a user input.

Currently I’m using an if statement that checks if the current animation tree node is equal to a string (the name of one of the nodes), traveling to the other node if they are, and traveling to the other if they aren’t.

As it is, the transition works only when they aren’t equal, so I tried printing whatever get_current_node() returns to see what I get, but when I did that nothing showed up in the output, and me being new to this, I thought maybe things that return null return nothing when printed, so I simply printed null, and that printed out the word Null just fine.

I’m still very now to godot and have very limited coding experience, so I’m certain there’s a better way to approach this, but I still don’t understand why get_current_node() isn’t returning anything. I receive no errors in the editor at any point.

This is the code I’m running:

extends KinematicBody2D

export var ACCELERATION = 500
export var MAX_SPEED = 90
export var FRICTION = 350
export var ROLL_SPEED = 500

enum {
	MOVE,
	DASH
}

var state = MOVE
var velocity = Vector2.ZERO

onready var animationTree = $AnimationTree
onready var animationState = animationTree.get("parameters/playback")
onready var animationPlayer = $AnimationPlayer
onready var currentAnimationState = animationState.get_current_node()

func _ready():
	animationTree.active = true

func _physics_process(delta):
	match state:
		MOVE:
			move_state(delta)
		DASH:
			dash_state(delta)

func move_state(delta):
	#determine direction
	var input_vector = Vector2.ZERO
	input_vector.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
	input_vector.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
	input_vector = input_vector.normalized()
	
	if input_vector != Vector2.ZERO:
		animationTree.set("parameters/IdleBlue/blend_position", input_vector)
		animationTree.set("parameters/IdleRed/blend_position", input_vector)
		velocity = velocity.move_toward(input_vector * MAX_SPEED, ACCELERATION * delta)
	else:
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
	
	move()
	
	if Input.is_action_just_pressed("dash"):
		state = DASH

func dash_state(_delta):
	#change color state
	if currentAnimationState == "IdleRed":
		animationState.travel("IdleBlue")
	else:
		animationState.travel("IdleRed")
	state = MOVE

func move():
	velocity = move_and_slide(velocity)
:bust_in_silhouette: Reply From: Zylann
onready var animationState = animationTree.get("parameters/playback")

I’m not experienced in AnimationTree, but this property is not documented anywhere. AnimationTree — Godot Engine (stable) documentation in English
What is this returning?
Using get with internal property paths is very uncommon, there should be a documented function or property giving you what you need.

So not knowing what this returns, I searched for aget_current_node() function in all the docs. The only one I could find is here: AnimationNodeStateMachinePlayback — Godot Engine (stable) documentation in English
It returns a string, which means your print was probably printing an empty string. So it appears like it’s not printing, but it does.
Empty string usually means “null”, in “string terms”. Maybe the state is not playing?

Because the AnimationTree can have many different node types (and nest them) the only way to get these elements is to use get. The editor tooltips let you see what the property path is and the type.

davidoc | 2020-04-28 14:52

That should be documented probably. Would be nice to have an explicit function or property we could use instead of this (if not, it should be added)

Zylann | 2020-04-28 17:47

It is documented: here. You can also use methods/properties from the tree_root property and it’s descendants, but in the end is like using get_node("really_long_path") instead of using node.get_child().get_child()

davidoc | 2020-04-28 18:14

I mean, that’s definitely a property of the node, it’s confusing to not find that present in the API doc itself, and buried in tutorial descriptions instead…
At least a function like set_parameter() instead of set("parameters/"), because everything in the API has this. It makes it searchable and completable.

Zylann | 2020-04-28 18:37

:bust_in_silhouette: Reply From: davidoc

You need to call the function in your _physics_process function, calling in at the begining will return the initial state, and if your state machine doesn´t have a start node it will be empty.

This was what went wrong. Soon after posting this question, I returned to see if I could work out what I did wrong. Since I defined currentAnimationState outside of any process loop, it’s value never changed.

By moving it into the _physics_process, it refreshed the value each loop and worked as expected.

Pumper | 2020-04-28 18:27

I don’t know if it’s worth noting, but I also subsequently found a better solution that got rid of the need to check the current node altogether by simply creating a function that, when called, changed the value of an enum between two states, and using that to determine which animation node should be travelled to.

Pumper | 2020-04-28 18:30

I’d recommend you to use advance conditions instead of travel, I made a tutorial you can find here, I find it more strightforward because you just need to calculate your conditions and pass them to the state machine.

davidoc | 2020-04-28 23:23