The correct way to change a variable at the end of process() and check it in the beginning of process()

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By mattpsd

I want to play a sound based on the frame of animation and I want it to play only once when the frame is first introduced. I got it working like this:

var stepPlayed = false

func stateRun():
	$AnimatedSprite.animation = "Run"

	if $AnimatedSprite.frame == 0 or $AnimatedSprite.frame == 4:
		if StepPlayed == false:
			$AudioStep.play()
			stepPlayed = true
			
	elif $AnimatedSprite.frame != 0 and $AnimatedSprite.frame != 4:
		stepPlayed = false

I believe this isn’t the most efficient way to do it since it can create tons of variables. Is there a way to solve it with declaring a variable in the scope of the stateRun() function? Or any even better ways to do it?

I know the problem can be approached with the AnimationPlayer node, but I don’t really like this solution because it creates a bunch of other problems.

And I sometimes encounter similar problems when coding not only with sound and animations, but generally with variables that need to be changed at the end of _physics_process(delta) and their state is read in the beginning of _physics_process(delta).

:bust_in_silhouette: Reply From: StefanoGrossiNature

I am a low level programmer and i can just suggest my approach.
GDScript dont support static variables so you need to make them global, if you need that a frame is only played once then you need to make an array(local to the module that is using it) parallel to each frame:

var playedframes[frames_num] = []

Fill it with zeros (int) and the beginning of your program,and when a frame is played you set it to 1,if is 1 then it’s played and you dont’ play it again:

if playedframes[$AnimatedSprite.frame]==0:
          play it
          playedframes[$AnimatedSprite.frame]=1    # set it to played

In your code there is a redundance by the way,this code is not needed:

elif $AnimatedSprite.frame != 0 and $AnimatedSprite.frame != 4:
        stepPlayed = false

I suggest you to design your code structure better BEFORE writing lines to have an optimal result.