Hello. I've been having this issue for a little while and I can't help but feel like there's something simple I'm missing. However, every attempt I've made at fixing it has been unsuccessful. I'm using Godot 4.0 Beta 11, but was having this issue on Beta 10 as well. I have a simple CharacterBody2D with a simple controller. I have a very simple 2 frame run animation, and a 1 frame idle animation. I'm using and animation player and an animation tree. The tree, animations, and character body are all set up as seen below.

extends CharacterBody2D

#movement
const ACCELERATION = 20
const FRICTION = 20

var max_speed = 40

#animation
var direction_facing = 1

@onready var animationPlayer = $AnimationPlayer
@onready var animationTree = $AnimationTree
@onready var skin = $Skin


func _physics_process(delta: float) -> void:
	#declare and set input vars
	var input_vector = Input.get_vector("move_left", "move_right", "move_up", "move_down")
	var input_axis = Input.get_axis("move_left", "move_right")

	#handle input and animation tree parameters, change velocity
	if input_vector != Vector2.ZERO:
		velocity = velocity.move_toward(input_vector * max_speed, ACCELERATION)
		animationTree["parameters/MoveState/current"] = 1
		animationTree["parameters/TimeScale/scale"] = (velocity.length())
		print(str(animationTree["parameters/MoveState/current"]) + " : " + str(animationTree["parameters/MoveState/time"]))
	if input_vector == Vector2.ZERO:
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION)
		animationTree["parameters/MoveState/current"] = 0
	move_and_slide()
	
	#flip skin based on aim
	if get_global_mouse_position().x < global_position.x:
		skin.scale.x = -1
	else:
		skin.scale.x = 1

Idle Animation

Move Animation

Animation Tree

Transition of Blend Tree Settings

Short Clip of What I'm Talking About:

I've Tried:

  • Messing with various inspector properties
  • Not using Timescale
  • Changing animation lengths
  • Changing animation blend types
  • Lots of other stuff I'm forgetting (I've tried a lot of things)

I've Noticed:

  • Doesn't always happen; I usually have to move around a bit before getting the frame to stick
  • Through debugging, I've found that the frame gets stuck only if you stop moving just as the move animation ends, or really close to it ending (at 1 second long, I must stop at exactly 1 second, but at 10 seconds long, I must stop at 9.666667 seconds). This range that determines whether the frame gets stuck or not seems to grow larger the faster the animation plays, whether that's from shortening the animation or increasing the timescale.
  • I originally thought that this issue stemmed from the timescale but have found that it still happens regardless of the timescale being there or not, so my best guess is that it's either an issue with how I have my animation player set up, an issue with my animation tree set up, or an issue in my code.

As of yet, I have not tried to replicate this issue in Godot 3.X yet, so it is possibly a bug. Testing it in 3.X is my next step once I get the time. I appreciate any and all help I receive and thank you for your work. I apologize if there are typos or issues with my post. This is my first time posting since the forum changed and it is currently 2:46 am. Again, thank you.

  • Megalomaniak Okay, I'll look into that. I found something though. When I set the idle animation to loop, the frame only gets stuck for the length of the idle animation. (set idle anim to loop and length to 5 secs and it'll get suck on the frame for 5 secs and then go back to normal.) So technically it's fixed if I set the idle animation to looping and set the length to 0 seconds. It also doesn't happen when I use an actual multi-frame idle animation (I created a 6 frame idle animation and it didn't get stuck, but came back when i removed the last five frames) So, to conclude, I believe this to be a bug with the way that frames are transitioned. The current workaround is to set the idle animation to looping and set the length to 0 seconds, or create a multiple frame idle animation. Thank you for your help and suggestions 🙂 I've never reported to the issue tracker but I'll give it a try. Thank you.

Okay so I just realized that this forum doesn't support embedded mp4 files (my bad) so here are screenshots from that clip:

Basically, when walking, the run animation alternates between these 2 frames and (usually) when stopping, it switches to the first frame. Occasionally, however, (the issue) it will stop on the second frame (legs stretched outwards) and stay like that until the player moves again.

Also sorry that only half of the code is actually there as code. I don't know how (or if you can) edit your discussion so here's that same code again for those that would like their eyeballs to remain healthy:

extends CharacterBody2D

#movement
const ACCELERATION = 20
const FRICTION = 20

var max_speed = 40

#animation
var direction_facing = 1

@onready var animationPlayer = $AnimationPlayer
@onready var animationTree = $AnimationTree
@onready var skin = $Skin


func _physics_process(delta: float) -> void:
	#declare and set input vars
	var input_vector = Input.get_vector("move_left", "move_right", "move_up", "move_down")
	var input_axis = Input.get_axis("move_left", "move_right")

	#handle input and animation tree parameters, change velocity
	if input_vector != Vector2.ZERO:
		velocity = velocity.move_toward(input_vector * max_speed, ACCELERATION)
		animationTree["parameters/MoveState/current"] = 1
		animationTree["parameters/TimeScale/scale"] = (velocity.length())
		print(str(animationTree["parameters/MoveState/current"]) + " : " + str(animationTree["parameters/MoveState/time"]))
	if input_vector == Vector2.ZERO:
		velocity = velocity.move_toward(Vector2.ZERO, FRICTION)
		animationTree["parameters/MoveState/current"] = 0
	move_and_slide()
	
	#flip skin based on aim
	if get_global_mouse_position().x < global_position.x:
		skin.scale.x = -1
	else:
		skin.scale.x = 1

    bloody-spuddy-buddy Okay so I just realized that this forum doesn't support embedded mp4 files (my bad) so here are screenshots from that clip:

    It does. auto embeds raw url's on new line. I've fixed the formatting, also of the codeblock, so it should all render fine now.

      It looks like it's stuck on a specific frame of the move state. So you should make sure it(animation tree) properly transitions to the idle state when the character stops moving. It also might be caused perhaps by the idle states animation having a length of 0 from what it looks like in the screenshot.

        Megalomaniak I've tried both of those and it doesn't fix it unfortunately. And the print statement says that it's properly switching states. I recreated the scene in 3.5.1 and although I did everything the exact same, I don't appear to be having the issue there, so until anything else comes forward, my best guess is that it's simply a bug. Tomorrow I'll port the 3.5.1 scene over to 4.0 and check again, just in case I accidentally did something different when recreating the scene.

          bloody-spuddy-buddy I recreated the scene in 3.5.1 and although I did everything the exact same, I don't appear to be having the issue there, so until anything else comes forward, my best guess is that it's simply a bug.

          I agree, it could well be a bug. Consider recreating a minimal project for reproducing it and reporting it to the issue tracker. Before you do any of that though, common courtesy would be to search the tracker, perhaps someone has already reported the issue.

            Megalomaniak Okay, I'll look into that. I found something though. When I set the idle animation to loop, the frame only gets stuck for the length of the idle animation. (set idle anim to loop and length to 5 secs and it'll get suck on the frame for 5 secs and then go back to normal.) So technically it's fixed if I set the idle animation to looping and set the length to 0 seconds. It also doesn't happen when I use an actual multi-frame idle animation (I created a 6 frame idle animation and it didn't get stuck, but came back when i removed the last five frames) So, to conclude, I believe this to be a bug with the way that frames are transitioned. The current workaround is to set the idle animation to looping and set the length to 0 seconds, or create a multiple frame idle animation. Thank you for your help and suggestions 🙂 I've never reported to the issue tracker but I'll give it a try. Thank you.