EDIT / WARNING: I updated the example to clean up the SceneTreeTimer, as it will still be counting and call resume()
twice. This fixes an error, but adds some distracting complexity to the code. The timer code can be ignored, its only to serve the example. If timers with yields are needed, I recommend using your own timers to have better control over them.
In addition to what you're doing, if you need to cancel a yield, you will want to keep track of the GDFunctionState
that the yield()
returns. https://docs.huihoo.com/godotengine/godot-docs/godot/classes/class_gdfunctionstate.html
A yield will return the function immediately with that object, and you can hold on to it and use it as you like.
First check if it is still is_valid()
, and then call resume()
to cancel the yield.
Additionally, you want to exit the function that is doing the yielding. To do this you can pass optional arguments into the resume(args)
, and capture them in var
and then use them in a following if
statement like you have above.
In your case, it is just return
.
Here I have an example of 5 second timer, where I'm using a button to do the cancel.
The flow can be confusing, since things are jumping around.
extends Node2D
const CANCEL = true
var timer
var pending_yield
func _ready():
pending_yield = do_stuff()
# This what comes back out of the return from a yielded function.
print(pending_yield)
func _on_Button_pressed():
print(pending_yield.is_valid())
if(pending_yield.is_valid()):
# Resume can pass a value back.
pending_yield.resume(CANCEL)
# Cleans up SceneTreeTimer
# Otherwise it will call resume() too.
timer.unreference()
timer = null
func do_stuff():
timer = get_tree().create_timer(5.0) # Keep reference to timer.
var result = yield(timer, "timeout")
print(result)
if(result and result == CANCEL):
print("The yield was cancelled. Stopping the function.")
return
print("Waited 5 seconds... carrying on.")
timer = null