Hey there, I know it’s a common issue beginners are having but when reading the others posts I didn’t find my answer.
I have a chicken that moves randomly on my screen, and switches “walking” animation to an “idle” animation. It works perfectly:
#Chicken Script
func _physics_process(delta):
var isLeft = velocity.x < 0
animated_sprite_2d.flip_h = isLeft
if (velocity.x > 1 || velocity.x < -1):
animated_sprite_2d.animation = "walking"
else:
animated_sprite_2d.animation = "idle"
if velocity.x == 0:
animated_sprite_2d.flip_h = randomIdle
move_and_slide()
#Direction Change, makes the chicken randomly stops for more natural movement
func _on_timer_timeout():
var randomIdle = true
if randf() < 0.5:
randomIdle = false
else:
randomIdle = true
if randf() < 0.6:
direction.x = 0
direction.y = 0
else:
direction.x = randf_range(-1.0,1.0)
direction.y = randf_range(-1.0,1.0)
pass
velocity = direction * randf_range(50,100)
The issue I’m having is that I have a monster entity that basically moves towards the closest chicken on the map, and then attacks the chicken. When the monster is attacking, I run the “attack” animation. When the “attack” animation is over, the monster gets stuck on the first “walking” frame, whereas it works perfectly before attacking:
#Monster Script
func _physics_process(delta):
if isAttacking == false: #this is how i managed to stop the monster from walking
newClosestChicken = find_closest_chicken()
direction = global_position.direction_to(newClosestChicken.global_position)
velocity = direction * 50
var isLeft = velocity.x < 0
animated_sprite_2d.flip_h = isLeft
if velocity.x != 0:
animated_sprite_2d.animation = "walking"
else:
animated_sprite_2d.animation = "idle"
move_and_slide()
func _on_pouler_attacked():
isAttacking = true
animated_sprite_2d.animation = "attack"
func _on_animated_sprite_2d_animation_finished():
isAttacking = false
Try to use animation_finished() signal on AnimatedSprite2D instead func _on_animated_sprite_2d_animation_finished(), because I think the problem is your var it’s not changing correctly. You can check what is happening if you put an else on if isAttacking == false: and print isAttacking variable.
I’m also recommended you to check state machines on Godot, it’s a system created for what you’re aiming for.
The variable is not the issue, otherwise the monster wouldn’t keep walking after killing the chicken. There seems to be something wrong with the animations.
And see when they are not called anymore. If you could post the same clip with this console message I’d appreciate it.
On the other hand, Are you sure find_closest_chicken() is working properly? are you doing queue_free to the previous chicken so it’s not found anymore?
Is the animation set to loop? Because maybe by the time the chicken is killed, the walking animation stops and when you try to get back to it, it’s over, so it’s just showing you the last frame.
If that doesn’t work, also press the “autoplay” button (to the right of the loop button)
If you play a loopable animation (like your “walking”) and you’ve started the animated_sprite somehow (calling “play” or by telling it to autoplay) the animation keeps playing. If you switch to another loopable animation, the animations keep playing and everything works fine.
BUT…
if you switch to a non-loopable animation (in your case, the “attack”) and that animation reaches the end, the animated_sprite STOPS COMPLETELY.
If you assign again the walking animation, it doesn’t matter, it won’t start. You need to call “play” to start the animation again.
I just tested it, switching between animations, and everything works fine (even changing animated_sprite.animation) but as soon as I let a non-loopable animation reach its end, everything stops.
Keep that in mind for the next time, even if you’re changing your code to a state machine, if you don’t handle this correctly you’ll keep having the same problem.
A quick fix is to make a method called “set_animation” and check if the animation is not started, then start it, with that you don’t have to worry about anything anymore.
func set_animation(animation_name):
animated_sprite_2d.animation = animation_name
if not animated_sprite_2d.is_playing():
animated_sprite_2d.play()