Using yield(get_tree().create_timer(x))

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

Hello,

I’m not certain I’m understanding how to properly use the yield(get_tree().create_timer(x)) coroutine.

func _physics_process(delta):
	wait_for_attack()
	
func wait_for_attack():
	yield(get_tree().create_timer(5.0), "timeout")
	print("begin attack")
	attack()

My expectation is that this will run once every 5 seconds. However, I’m seeing that it waits 5 seconds the first time, and after the yield completes, the code after the yield continues to get called every frame as if the yield isn’t there. Am I missing something?

I don’t think yield is a good way to do that. Both answers of this are better.

Masoud | 2019-05-04 15:25

This behavior is because you create a timer every time phyiscs_process is called, so the first timer will fire 5 secs after the first call to phys_process and then every frame after that the next created timer will fire.

omggomb | 2019-05-04 15:34

I see what you’re saying. So the code is executing exactly as I told it to do. I incorrectly assumed that it wouldn’t call the yield again until it had finished.

2ndGarrison | 2019-05-04 19:14

1 Like
:bust_in_silhouette: Reply From: 2ndGarrison

Thanks @omggomb, your comment led me to look up the documentation. After taking a look, I was able to figure out a way to make it work with yield.

var attack_timer

func _ready():
	attack_timer = get_tree().create_timer(0.0)

func _physics_process(delta):
	wait_for_attack()

func wait_for_attack():
	if attack_timer.time_left <= 0.0:
		attack_timer = get_tree().create_timer(5.0)
		yield(attack_timer, "timeout")
		attack()

This will only execute every 5 seconds.

However, the answers linked by @Masoud may be a better solution for this. The second answer is a somewhat cleaner approach.