How do I replace all "yield" timers with normal Timers when the function has multiple "yield" timers

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

I recently found out that “yield” timers are generally bad to use and should be avoided, however I can’t use a Timer’s “timeout” function as some of the code has multiple “yield” timers.

if Input.is_action_just_pressed("dash"):
			if canDash == true and starActive == false:
				speed *= dashSpeed
				yield(get_tree().create_timer(0.1), "timeout")
				speed = baseSpeed
				canDash = false
				yield(get_tree().create_timer(0.5), "timeout")
				canDash = true

the first timer is so that it sets back to normal speed and the second timer is the cooldown. Is there anyway to work around this?

:bust_in_silhouette: Reply From: Lopy

To avoid confusions, what you call “yield” timers are actually SceneTreeTimers. You can ctrl+click on the create_timer function to open it’s documentation.

How to do it

Here is an example script making use of a regular Timer named Timer, placed as a child of this script, with yields like in yours:

extends Node

var start_time: int # miliseconds
onready var timer: Timer= $Timer

func _ready() -> void:
    start_time = OS.get_ticks_msec()
    timer.one_shot = false # Disable repeats
    yield(timer, "timeout")
            " seconds elapsed in total")
    yield(timer, "timeout")
            " seconds elapsed in total")
    yield(timer, "timeout")
            " seconds elapsed in total")

Why I dislike the question

Not against you, but against calling things “bad” and “good”. You say that you want to avoid SceneTreeTimers because they are “bad”, I say calling tools “bad” or “good” is a bad idea, because it hides all the important details that tell you when and how to use them. The main advantage of a SceneTreeTimer is practicality, and the main disadvantage is that an object is created every time you want a timer. Now, while this may seem problematic, you would need to create a huge number of them to notice any slowdown. Optimizing before you detect the need to is called premature optimization, and tends to make code unnecessarily complicated. Also, to make optimizations you need to check the speed of your code using tools like a profiler, otherwise you might “optimize” into code that is actually slower because you made a wrong assumption.

Now, in this case I would say that either solution works fine, I just want to warn against putting unconditional “good” or “bad” label on things.