Animation is stuck on the first frame

Godot Version

4

Question

tried fixing this for about a week on and off while on other animations, and some of them in implimented just dont play in game, and only play the first frame, the only thing that works is the running animation which is tied to a directional input command. everything just doesnt play at all

		parasol_girl.play("running")
	else:
		parasol_girl.play("idle")
		
	if  not is_on_floor():
		parasol_girl.play("jumping")
	if jump_count >=2:
		parasol_girl.play("double_jump")
		
	if Input.is_action_pressed("ui_down"):
		is_crouching = true
		parasol_girl.play("crouching")
		collision.disabled = true
		crouch_shape.disabled = false
		horizontal_direction = false
		
	elif Input.is_action_just_released("ui_down"):
		is_crouching =  false
		horizontal_direction = true
		collision.disabled = false
		crouch_shape.disabled = true
		
	if velocity.y >= 1:
		parasol_girl.play("falling")
		
	if dash_state:
		parasol_girl.play("dashing")```

This is the part who make the problems. The “else” statement launch the “idle” animation every frame and another override it right after in the other condition and restart from first. You must check than any other animation need to be played to launch the “idle” one.

1 Like

i had idle set based on if the player was moving around the x axis but that still didnt work and the only animation that plays fully is the running animation which is weird as heck

I need the entire script to show you how it can be done. By now I can only extrapolate this (not tested at all) :

Movement for CharacterBody2D
func _physics_process(delta):

	# Max priority to the dash animation
	if dash_state:
		parasol_girl.play("dashing")
	else:
		
		if is_on_floor(): # Floor animation first
			jump_count = 0
			if Input.is_action_pressed("ui_down"): # Crouch animation first 
				is_crouching = true
				parasol_girl.play("crouching")
				collision.disabled = true
				crouch_shape.disabled = false
				horizontal_direction = false
			elif Input.is_action_just_released("ui_down"): # Then uncrouch
				is_crouching =  false
				horizontal_direction = true
				collision.disabled = false
				crouch_shape.disabled = true
			elif abs(velocity.x) > 0.1: # Then Running
				parasol_girl.play("running")
			else: # Then if nothing else is triggered IDLE
				parasol_girl.play("idle")
				
		else: # Air animation

			if velocity.y >= 1: # if falling
				parasol_girl.play("falling")
		
		# Jump
		if Input.is_action_just_pressed("ui_up") and jump_count < 2: # Jump button pressed
			velocity.y -= JUMP_VELOCITY
			jump_count += 1
			if jump_count >= 2: # if double jump
				parasol_girl.play("double_jump")
			else: # if simple jump
				parasol_girl.play("jumping")

	move_and_slide()

EDIT :
Changed the code a bit because jump must be checked after floor or air check

1 Like

sorry it took so long, i was abit busy ._.

@onready var parasol_girl = $AnimatedSprite2D
@onready var collision = $CollissionShape2D
@onready var dash_shape = $dash_shape
@onready var crouch_shape = $crouch_shape
#const SPEED = 400.0 # Imahilus doesn't appear to be used
var speed = 350.0
# Jumping variables
const JUMP_VELOCITY = -480.0
const FAST_FALL_VELOCITY = 1000
var jump_count = 0
var max_jumps = 2
var fast_fall = false
# Dashing variables
const DASH_SPEED = 2000
var dash_state = false
@export var dash_duration = 0.1
var time_spent_dashing = 0
@export var dash_cooldown = 1
var time_dash_spent_on_cooldown = 0
@onready var second_jump: bool = false
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var is_crouching = false
var vertical_direction = Input.get_axis("ui_down","ui_up")
var super_jump = false
var super_jump_height = -480

func _physics_process(delta):
	print(is_near_wall())
	var horizontal_direction = Input.get_axis("ui_left","ui_right")
	if is_crouching:
		horizontal_direction = 0.0
	# Imahilus: I've commented this out, as the physics engine will apply the gravity to CharacterBody2D if 'motion_mode' is set to 'grounded' in the Inspector
	#Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta
	
	# Time to handle the jump
	if is_on_floor():
		# We're on the floor, let's reset any jumps including the 'downwards jump'
		jump_count = 0
		fast_fall = false
	
	if Input.is_action_just_pressed("jump") and jump_count < max_jumps:
		jump_count += 1
		velocity.y += JUMP_VELOCITY
		
	if !fast_fall and Input.is_action_just_pressed("ui_down") and !is_on_floor():
		# If no 'downwards jump' has been triggered yet, we press the button to 'downward jump' AND we're not on the floor, do the drop!
		fast_fall = true
		jump_count = max_jumps # if we jump downwards.. no more jumping up!
		
		
	if fast_fall:
		# we're jumping downwards!! wheeee!
		velocity.y = FAST_FALL_VELOCITY
	
	# Imahilus: I've commented this out, and rewritten this above
	#if Input.is_action_pressed("ui_down"):
	#	velocity.y = velocity.y +70
	
	#if is_on_floor():
	#	jump_count = 0
	
	# Handle jump.
	#if Input.is_action_just_pressed("ui_accept") and jump_count < max_jumps:
	#	if jump_count==0:
	#		velocity.y = JUMP_VELOCITY
	#		jump_count += 1
	#	elif jump_count==1:
	#		velocity.y= JUMP_VELOCITY+double_jump
	#		jump_count+=1
		
			
			# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	#	if Input.is_action_just_pressed("ui_accept") and jump_count < max_jumps:
	#		if jump_count==0:
	#			velocity.y = JUMP_VELOCITY
	#			jump_count += 1
	#		elif jump_count==1:
	#			velocity.y= JUMP_VELOCITY*double_jump
	#			jump_count+=1
		
		
	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	if Input.is_action_just_pressed("Dash") and time_dash_spent_on_cooldown >= dash_cooldown: # If the button is pressed, and the last time Dash was used is longer than the cooldown time ago, we can dash!
		dash_state = true
		time_spent_dashing = 0 # reset the time we've spent Dashing
		time_dash_spent_on_cooldown = 0 # reset the cooldown on the Dash
		
	if dash_state:
		collision.disabled = true
		dash_shape.disabled= false
		velocity.y = 0
	else:
		collision.disabled = false
		dash_shape.disabled = true
	
	if dash_state:
		# We're dashing!!
		
		# Lets update the timers of the dash, so we don't permanently dash
		time_spent_dashing += delta
		if time_spent_dashing >= dash_duration:
			dash_state = false # We've spent more time dashing than was set, so we need to stop
		
		# Now lets actually do the dash part of it
		if parasol_girl.flip_h == false:
			# If parasol_girl is facing right; we dash to the right
			velocity.x = DASH_SPEED
		else:
			# If parasol_girl is facing left; we dash to the left
			velocity.x = -DASH_SPEED
	else:
		# We're not dashing... so we can look at normal input. We separate these 2 so that user controls can't influence the dash
		velocity.x = speed * horizontal_direction
	if velocity.x > 0:
		parasol_girl.flip_h = false
	elif velocity.x < 0:
		parasol_girl.flip_h = true
	
	# Last thing to do, if Dash is on cooldown, we need to count this time towards the cooldown, otherwise it won't come back
	# This can't be in with the Dash code because it has to happen regardless of whether we're dashing
	if time_dash_spent_on_cooldown < dash_cooldown:
		# We only need to do this until we've waited long enough (see line 67; until time_dash_spent_on_cooldown is more or equal to dash_cooldown)
		time_dash_spent_on_cooldown += delta
		
	
	move_and_slide()
	
	# Regardless of what we did in any if statement, if parasol_girl has any velocity, let the physics engine move her
	if horizontal_direction:
		parasol_girl.play("running")
	else:
		parasol_girl.play("idle")
		
	if  not is_on_floor():
		parasol_girl.play("jumping")
	if jump_count >=2:
		parasol_girl.play("double_jump")
		
	if Input.is_action_pressed("ui_down"):
		is_crouching = true
		parasol_girl.play("crouching")
		collision.disabled = true
		crouch_shape.disabled = false
		horizontal_direction = false
		
	elif Input.is_action_just_released("ui_down"):
		is_crouching =  false
		horizontal_direction = true
		collision.disabled = false
		crouch_shape.disabled = true
		
	if velocity.y >= 1:
		parasol_girl.play("falling")
		
	if dash_state:
		parasol_girl.play("dashing")
func is_near_wall():
	return $Wall_Checker.is_colliding()```

ok almost everything worked! perfectly, theres ONLY 2 issues, the dash plays pass the dash state. so like, im able to see the actual dash frame for an extended period of time and even normally movearound in it without the running animation playing for abit.

the second issue is that i cant get the falling animation. also your jump animation code caused me to have 3 jumps so i just quickly fixed that :stuck_out_tongue: no big deal, and the abs running animation code caused the jumping animations to end early so i just changed it back to horizontal direction and that fixed it. besides those two problems idk how to fix, everything else is fine, ty

Hi,
There is a lot of thing you can improve in your current code and small thing you forget. If you resend it with the modification you made for the animation I can show you what to do. By the way, you can use a timer node on your player for your dash cooldown instead of your own variable.

@onready var parasol_girl = $AnimatedSprite2D
@onready var collision = $CollissionShape2D
@onready var dash_shape = $dash_shape
@onready var crouch_shape = $crouch_shape
#const SPEED = 400.0 # Imahilus doesn't appear to be used
var speed = 400.0
# Jumping variables
const JUMP_VELOCITY = -480.0
const FAST_FALL_VELOCITY = 1000
var jump_count = 0
var max_jumps = 2
var fast_fall = false
# Dashing variables
const DASH_SPEED = 2000
var dash_state = false
@export var dash_duration = 0.1
var time_spent_dashing = 0
@export var dash_cooldown = 1
var time_dash_spent_on_cooldown = 0
@onready var second_jump: bool = false
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var is_crouching = false
var vertical_direction = Input.get_axis("ui_down","ui_up")
var super_jump = false
var super_jump_height = -480

func _physics_process(delta):
	print(is_near_wall())
	var horizontal_direction = Input.get_axis("ui_left","ui_right")
	if is_crouching:
		horizontal_direction = 0.0
	# Imahilus: I've commented this out, as the physics engine will apply the gravity to CharacterBody2D if 'motion_mode' is set to 'grounded' in the Inspector
	#Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta
	
	# Time to handle the jump
	if is_on_floor():
		# We're on the floor, let's reset any jumps including the 'downwards jump'
		jump_count = 0
		fast_fall = false
	
	if Input.is_action_just_pressed("jump") and jump_count < max_jumps:
		jump_count += 1
		velocity.y += JUMP_VELOCITY
		
	if !fast_fall and Input.is_action_just_pressed("ui_down") and !is_on_floor():
		# If no 'downwards jump' has been triggered yet, we press the button to 'downward jump' AND we're not on the floor, do the drop!
		fast_fall = true
		jump_count = max_jumps # if we jump downwards.. no more jumping up!
		
		
	if fast_fall:
		# we're jumping downwards!! wheeee!
		velocity.y = FAST_FALL_VELOCITY
	
	# Imahilus: I've commented this out, and rewritten this above
	#if Input.is_action_pressed("ui_down"):
	#	velocity.y = velocity.y +70
	
	#if is_on_floor():
	#	jump_count = 0
	
	# Handle jump.
	#if Input.is_action_just_pressed("ui_accept") and jump_count < max_jumps:
	#	if jump_count==0:
	#		velocity.y = JUMP_VELOCITY
	#		jump_count += 1
	#	elif jump_count==1:
	#		velocity.y= JUMP_VELOCITY+double_jump
	#		jump_count+=1
		
			
			# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	#	if Input.is_action_just_pressed("ui_accept") and jump_count < max_jumps:
	#		if jump_count==0:
	#			velocity.y = JUMP_VELOCITY
	#			jump_count += 1
	#		elif jump_count==1:
	#			velocity.y= JUMP_VELOCITY*double_jump
	#			jump_count+=1
		
		
	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	if Input.is_action_just_pressed("Dash") and time_dash_spent_on_cooldown >= dash_cooldown: # If the button is pressed, and the last time Dash was used is longer than the cooldown time ago, we can dash!
		dash_state = true
		time_spent_dashing = 0 # reset the time we've spent Dashing
		time_dash_spent_on_cooldown = 0 # reset the cooldown on the Dash
		
	if dash_state:
		collision.disabled = true
		dash_shape.disabled= false
		velocity.y = 0
	else:
		collision.disabled = false
		dash_shape.disabled = true
	
	if dash_state:
		# We're dashing!!
		
		# Lets update the timers of the dash, so we don't permanently dash
		time_spent_dashing += delta
		if time_spent_dashing >= dash_duration:
			dash_state = false # We've spent more time dashing than was set, so we need to stop
		
		# Now lets actually do the dash part of it
		if parasol_girl.flip_h == false:
			# If parasol_girl is facing right; we dash to the right
			velocity.x = DASH_SPEED
		else:
			# If parasol_girl is facing left; we dash to the left
			velocity.x = -DASH_SPEED
	else:
		# We're not dashing... so we can look at normal input. We separate these 2 so that user controls can't influence the dash
		velocity.x = speed * horizontal_direction
	if velocity.x > 0:
		parasol_girl.flip_h = false
	elif velocity.x < 0:
		parasol_girl.flip_h = true
	
	# Last thing to do, if Dash is on cooldown, we need to count this time towards the cooldown, otherwise it won't come back
	# This can't be in with the Dash code because it has to happen regardless of whether we're dashing
	if time_dash_spent_on_cooldown < dash_cooldown:
		# We only need to do this until we've waited long enough (see line 67; until time_dash_spent_on_cooldown is more or equal to dash_cooldown)
		time_dash_spent_on_cooldown += delta
		
		if dash_state:
			parasol_girl.play("dashing")
	else:
		
		if is_on_floor(): # Floor animation first
			if Input.is_action_pressed("ui_down"): # Crouch animation first 
				is_crouching = true
				parasol_girl.play("crouching")
				collision.disabled = true
				crouch_shape.disabled = false
				horizontal_direction = false
			elif Input.is_action_just_released("ui_down"): # Then uncrouch
				is_crouching =  false
				horizontal_direction = true
				collision.disabled = false
				crouch_shape.disabled = true
			elif horizontal_direction: # Then Running
				parasol_girl.play("running")
			else: # Then if nothing else is triggered IDLE
				parasol_girl.play("idle")
				
		else: # Air animation
		
		# Jump
			if jump_count >= 2: # if double jump
				parasol_girl.play("double_jump")
			else: # if simple jump
				parasol_girl.play("jumping")
	move_and_slide()
	
	# Regardless of what we did in any if statement, if parasol_girl has any velocity, let the physics engine move her
func is_near_wall():
	return $Wall_Checker.is_colliding()
	
var direction = 1
func set_direction():
	direction = 1 if not parasol_girl.flip_h else -1
	$Wall_Checker.rotation_degrees = 90 * -direction```

btw i dont need use to the timer node, the dash works perfectly fine the way it is right now. and i dont wish to mess with it only to just break it again x.x

There is an indentation problem here. This need to be like this :

	# Last thing to do, if Dash is on cooldown, we need to count this time towards the cooldown, otherwise it won't come back
	# This can't be in with the Dash code because it has to happen regardless of whether we're dashing
	if time_dash_spent_on_cooldown < dash_cooldown:
		# We only need to do this until we've waited long enough (see line 67; until time_dash_spent_on_cooldown is more or equal to dash_cooldown)
		time_dash_spent_on_cooldown += delta
		
	if dash_state:
		parasol_girl.play("dashing")
	else:
		if is_on_floor(): # Floor animation first