im making a wolfenstein 3d clone, and im using a delta counter for fire delay (the games fps and animations fps is at the same value of 35) of the fully automatic weapon, and the weapon uses a animatedsprite2d:



the issue that im having is that when the fire animation is set to loop, after releasing fire it will replay the animation for a frame instead of immediately playing idle like whats supposed to happen:

and if the fire animation is not set to loop it will do this:

code:

extends Node3D

@onready var Weapon_Sprite = $CanvasLayer/Control/WeaponSprite

@onready var Hitscan = $Hitscan.get_children()

#animation fps and game fps at same value of 35fps
#weapon firing animation has 2 frames, each lasting 3 frames

#weapon cooldown delta counter vars
var can_fire = true
var fire_rate = 6
var fire_timer = fire_rate

func _ready():
	Weapon_Sprite.play("Idle")
	
func check_hit():
	for ray in Hitscan:
		if ray.is_colliding():
			if ray.get_collider().is_in_group("Enemy"):
				ray.get_collider().take_damage(5)
	
func _process(delta):
	#weapon cooldown delta counter
	#if cannot fire, then
	if can_fire == false:
		#if timer above 0, subtract timer by one each frame
		if fire_timer > 0:
			fire_timer -= 1
		#if timer is 0, set timer to fire rate and you can fire again
		if fire_timer == 0:
			fire_timer = fire_rate
			can_fire = true
			if not Input.is_action_pressed("main_fire_weapon"):
				Weapon_Sprite.play("Idle")
	#if holding fire and can fire, fire
	if Input.is_action_pressed("main_fire_weapon") and can_fire:
		Fire()
		
	#if not holding fire and cannot fire, play idle
	#if not Input.is_action_pressed("main_fire_weapon") and can_fire:
		#Weapon_Sprite.play("Idle")
		
func Fire():
	Weapon_Sprite.play("Fire")
	can_fire = false
	check_hit()
	#audio player
	$Fire.play()
  • xyz replied to this.

    JetteBoyTV This again? You're basically posting about the same problem over and over, just in slightly different forms. As I told you several times earlier, the root of all your weapon animation problems is that you count sprite frames on your own in _process(), independently of animated sprite node's frame counting. Even if animation and game fps are seemingly set to the same number, it's never guaranteed that they'll run fully in sync, due to frame drops and other gpu related stuff. The chances of mismatch are high so what you count in _process() may actually not represent your animation state. Since the engine always knows the animations state, best to just ask for it instead of maintaining your own "timer" property independently of the actual state.

    There also may be other logical errors there again, on top of bugs caused by improper frame counting. The code looks overly complicated for what it's supposed to do. But first fix the frame counting, then we can see about the rest.

      xyz would it be possible to set the animated sprite 2d's frame rate to exactly the delta value, not just having the same value of 35, but actually using the exact delta value for the frame rate, so that when there is frame drops there wont be mismatch because the animated sprite will also frame drop since it would be at the exact same value

      • xyz replied to this.

        JetteBoyTV It's possible, you can just manually update sprite's frame property. But why do this when engine is already doing it. You'd just overcomplicate the whole thing even more with more excess code, and how you currently trying to handle this is already needlessly complicated.

        Forget _process(), you don't need it at all for this. Not sure why you repeatedly insist on doing it like that while stumbling on the same problem again and again. Wouldn't you say that's a hint that this is a bad approach?

        Do everything in frame_changed and animation_finished signal handlers. That's the way to properly solve this.