hello, Is there a way to make the animation frames to run at the same speed has physics_process ?

Iam using this code to stop the physics_process

	if ( pauseTimer >= 0 ):
		pauseTimer -= 0.02;
		if ( pauseTimer <= 0 ):
			pauseTimer = 0;
		elif  ( pauseTimer != 0 ):
			return;
			#pass

but the animation has its own process it keeps playing ?

Ive used diferent ways to stop the animation and it works... But the problem is it starts getting 1 cicle of delay with an animation speed above 23 ? This means if i have to stop at frame 1 it will stop at frame 2 because the speed is to high.

func animationPlay(animNodee, animName, AnimSpeed, loop ):
	animNodee.frames.set_animation_speed(animName, AnimSpeed);
	animNodee.frames.set_animation_loop(animName, loop);
	animNodee.play(animName);
	if ( pauseTimer != 0 ):
		animNodee.stop();
	else:
		animNodee.play(animName);
	pass

player script

    		"st_attack":
    			animationPlay(anim, "attack", 30, false );
    			$hitBox.hitPauseTime = 3.3;
    			
    			if ( anim.frame == 1 ):
    				hitBox.disabled = false;
    				$hitBox.hitFacing = my_direction;
    			else :
    				hitBox.disabled = true;

Ive tried diferent ways putting the code right below if ( anim.frame == 1 ), but nothing seems to work. I always get 1 cicle in delay before the engine checks frame 1 shoud be stooped for 3.3 secs

It seems like the best way is to make the animation play at the same speed has the physics_process. If the physics_process returns ( exits the function ) the animation stops. Is there a way to do it ?

BTW the hit box hitPauseTime

func _ready():
	attacker = get_owner();
	victim = 0;
	pass

func _on_hitBox_area_entered(area: Area) -> void:
	victim = area.get_owner();
	victim.state = "st_pain2";
	victim.anim.frame = 0;
	
	
	if ( hitPauseTime > 0 ):
		attacker.pauseTimer = hitPauseTime;
		victim.pauseTimer = hitPauseTime;

Not sure what exactly you want to accomplish with this. Perhaps try to describe the final results you're after, maybe there's an entirely different approach to achieve it.

That said, you can manually advance the animation. Don't call play() at all but use AnimationPlayer.seek(time, true) and AnimationPlayer.advance(delta) to position the "playhead" and move it forward (or not) by wanted delta each frame.

Iam using the 'animatedSprite 3D'... Those features seemed to work for 'AnimationPlayer' In animated sprite i can only access the speed by using $playerAnim.frames.set_animation_speed("walk", 10);

iam trying to make a hitPause effect, but i cant get the yield() function to work very well, and it stops the entire tree. ive tried using $playerAnim.frames.set_animation_speed("walk", 10*delta); in phy process but the result was the same, the animation would keep playing or i would still keep 1 cicle in delay

Well then it's even easier. You can simply manually update sprite's frame property based on time passed.

@xyz said: Well then it's even easier. You can simply manually update sprite's frame property based on time passed.

yeah but... thats the thing i dont know. you mean create a timer like the 'pauseTimer ' ?

    if ( pauseTimer >= 0 ):
        pauseTimer -= 0.02;
        if ( pauseTimer <= 0 ):
            pauseTimer = 0;

That could work once the timer reaches '0' the frame updates +1

Something like the following (code not tested, writing from the top of my head)

var sprite_time = 0.0
var sprite_paused = false

func _physics_process(delta):
	if not sprite_paused:
		var frame_count = $sprite.frames.get_frame_count([$sprite.animation]) 
		var fps = $sprite.frames.get_animation_speed([$sprite.animation]) 	
		var total_anim_time =  frame_count / fps
		sprite_time = wrapf(sprite_time + delta, 0.0, total_anim_time)
		$sprite.frame = int(sprite_time/fps)

The code does something similar to your idea. It basically maintains a custom time variable, wraps it around the total animation duration, and uses it to calculate the frame number that should be displayed.

Note that you can use any custom fps, doesn't need to be the one set in the animation.

thanks i tested your code the animation is playing to fast and not reaching its end it might be something in frame_count * fps but ill get it working somehow, thanks

My mistake, that should be

var total_anim_time =  frame_count / fps

To make animation slower just use some literal value for fps that looks right.

Whether the animation plays or not depends on the state of sprite_paused flag. So check the logic that affects it. If this flag is always false, the animation should loop incessantly.

The gist of it is to set the frame property directly, not letting the animation do it. That way you have complete control over it.

@xyz said: My mistake, that should be

var total_anim_time =  frame_count / fps

To make animation slower just use some literal value for fps that looks right.

Whether the animation plays or not depends on the state of sprite_paused flag. So check the logic that affects it. If this flag is always false, the animation should loop incessantly.

The gist of it is to set the frame property directly, not letting the animation do it. That way you have complete control over it.

not sure if i can get it to work, i may be able to change the speed by using values var total_anim_time = frame_count / 0.00006 # 0

but the frame seems to be looping between the 1st frame and last frame ( in some cases )

If you want to freeze the animation, just set sprite_paused to true. When you want it to continue - set it to false. Is this the behavior you want or something else? Do you have a visual example of the effect you're after?

@xyz said: If you want to freeze the animation, just set sprite_paused to true. When you want it to continue - set it to false. Is this the behavior you want or something else? Do you have a visual example of the effect you're after?

the effect is the same has in the 2.5D beat em ups ( final fight / cadillacs and dinasours ) a hit paused when an attack connects.

Ive already managed to do it by increasing the frame +1, and then pause/exit the physics process. the only problem is reseting the animation frame to Zero when a new animation plays

onready var anim = $playerAnim;

var frameDelay = 0.03;
var frameTimer = 1;
var d_frame = 0;


func _physics_process(delta: float) -> void:

	if ( frameTimer > 0 ):
		frameTimer -= frameDelay;
	elif ( frameTimer <= 0  ):
		frameTimer = 1;
		
		var frame_count = anim.frames.get_frame_count(anim.animation); # nr of frames in animation
		var frame_loop =  anim.frames.get_animation_loop(anim.animation); # is loop ?
		
		if ( d_frame < frame_count ):
			d_frame += 1;
		elif ( frame_loop == true ):
			d_frame = 0;
	

	anim.frame = d_frame;

	match state:
			"st_idle":
				_move();
				_attack();
				$playerAnim.play("idle");
	
			"st_walk":
				_move();
				_attack();
				$playerAnim.play("walk");

In here if the frame is on number 3 the walking state anim will start at frame 3

Try to simply set the frame to zero before starting to play other animation.

@xyz said: Try to simply set the frame to zero before starting to play other animation.

thanks, i have it working now, i had to make a new function to replace the code state = "st_attack"

func changeState(stateName):
	if ( state != stateName ):
		state = stateName;
		d_frame = 0;

this way the animation resets to frame 0 everyTime it changes state. But the code is getting messy

When code gets messy, just try to reorganize into neat small functions that do exactly what their name is saying :)

a year later