When I use an AnimationTree the sprite of the character doesn't transition properly

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

I wanted to implement a Finite State Machine in my project, I followed the tutorial by GDQuest and everything worked fine.

After that I decided to implement an AnimationPlayer but I noticed that since my character can move in four directions, I wanted to see if I could find a better approach to avoid making tons of if/elif/else statements like this:

if Input.is_action_pressed("move_down"):
	player.animation_player.play("WalkDown")
elif Input.is_action_pressed("move_left"):
	player.animation_player.play("WalkLeft")
elif Input.is_action_pressed("move_right"):
	player.animation_player.play("WalkRight")
elif Input.is_action_pressed("move_up"):
	player.animation_player.play("WalkUp")

So I decided to to follow HeartBeast’s RPG tutorial where he uses an AnimationTree. The problem, comes when I play the scene and I try to move y character, I don’t quite understand what’s happening, but it’s like the moving animation can’t properly play and it switches immediately to the “Idle Left” animation. Here’s a quick video showcasing the error.

Like I mentioned before, I followed GDQuest’s FSM tutorial, so I have an Idle state that looks like this:

extends Motion

class_name Idle

# Upon entering the state, we set the Player node's velocity to zero.
func enter(_msg := {}) -> void:
	player.velocity = Vector2.ZERO
	speed = 0.0
	#print_debug(input_direction)
	player.animate("Idle", input_direction)
	#animate()


func update(delta: float) -> void:
	#animate()
	#player.animate("Idle", input_direction)
	if (Input.is_action_pressed("move_left") or 
		Input.is_action_pressed("move_right") or 
		Input.is_action_pressed("move_up") or 
		Input.is_action_pressed("move_down")):
			state_machine.transition_to("Move")

A moving state that looks like this:

extends Motion

class_name Move

var move_state_name: String

func _physics_process(delta: float) -> void:
	if Input.is_action_pressed("run"):
		move_state_name = "run"
		speed = player.MAX_RUNNING_SPEED
	else:
		move_state_name = "walking"
		speed = player.MAX_SPEED
	input_direction = get_input_direction()
	
	_move(delta)
	
func _move(delta) -> void:
	if input_direction != Vector2.ZERO:
		move_state_name = "move"
		player.animate("Walk", input_direction)
		#animate()
		player.velocity = player.move_and_slide(input_direction * speed, Vector2.ZERO)
		return
	else:
		#player.animation_state.stop()
		player.velocity = player.velocity.move_toward(Vector2.ZERO, player.FRICTION * delta)
		state_machine.transition_to("Idle")

And a player script that looks like this:

extends KinematicBody2D

class_name Player

export var MAX_SPEED = 600
export var MAX_RUNNING_SPEED = 650
export var ACCELERATION = 50
export var FRICTION = 900

onready var animation_player = $AnimationPlayer
onready var animation_tree = $AnimationTree
onready var animation_state = animation_tree.get("parameters/playback")

export var velocity = Vector2.ZERO

# Called when the node enters the scene tree for the first time.
func _ready():
	#get_node("Sprite").frame = 0
	pass # Replace with function body.
	
func animate(animationName: String, input_vector: Vector2) -> void:
	var params_text = "parameters/{animationName}/blend_position"
	params_text = params_text.format({"animationName": animationName})
	
	print_debug("Params Text: ", params_text)
	animation_tree.set(params_text, input_vector)
	animation_state.travel(animationName)
	return

A few things that I noticed while trying to solve the error, my character has a Sprite node where I put the sprite sheet, the frame of the sprite, under navigation, seems to be locked, if I try to change it it reverts back to Frame: 1 for some reason. Another thing is that if I try to use the if/elif/else method that I mentioned at the beginning with the AnimationPlayer instead of the AnimationTree it actually works normally. The problem comes when I try to use the AnimationTree.

What solved the issue for me was to set the AnimationTree as active from the code instead of doing it directly on the AnimationTree node.

func _ready():
	# The animation tree is set to inactive, and I set it to active in 
	# the ready function of my Player script
	animation_tree.set_active(true)

Another issue I had was that I was setting the blend position of the AnimationTree (animation_tree.get(“parameters/playback”)) every time my state machine transitioned into a new state. I solved this by setting the blend position of my Idle and Move animations in my Move state, which is where I get the input vector with the direction the sprite should be facing.

So my Player script has a function like this and I just call that function from my Move state:

func set_animation_tree_blend_positions(input_vector: Vector2) -> void:
	#print("Blend Position: ", input_vector)
	animation_tree.set("parameters/Idle/blend_position", input_vector)
	animation_tree.set("parameters/Walk/blend_position", input_vector)

pizza_party | 2023-01-17 00:10

:bust_in_silhouette: Reply From: pizza_party

What solved the issue for me was to set the AnimationTree as active from the code instead of doing it directly on the AnimationTree node.

func _ready():
    # The animation tree is set to inactive, and I set it to active in 
    # the ready function of my Player script
    animation_tree.set_active(true)

Another issue I had was that I was setting the blend position of the AnimationTree (animation_tree.get(“parameters/playback”)) every time my state machine transitioned into a new state. I solved this by setting the blend position of my Idle and Move animations in my Move state, which is where I get the input vector with the direction the sprite should be facing.

So my Player script has a function like this and I just call that function from my Move state:

func set_animation_tree_blend_positions(input_vector: Vector2) -> void:
    #print("Blend Position: ", input_vector)
    animation_tree.set("parameters/Idle/blend_position", input_vector)
    animation_tree.set("parameters/Walk/blend_position", input_vector)