Topic was automatically imported from the old Question2Answer platform.
Asked By
jacktype
Hello,
I’m trying to resume a yielded function. The function consists of a 5 second timer that when completes sucessfuly prints a message “Waited 5 seconds”, otherwise if a button is pressed in the middle of the timer execution the function exits and prints “yield cancelled”.
This code works correctly but the debugger shows an error resume: Condition "!function" is true. Returned: Variant()
I can’t figure out the reason for this error.
code:
extends Node2D
const CANCEL = true
var pending_yield
func _ready():
pending_yield = do_stuff()
func _on_Button_pressed():
if(pending_yield.is_valid()):
pending_yield.resume(CANCEL)
func do_stuff():
var result = yield(get_tree().create_timer(5), "timeout")
if result == CANCEL:
print("The yield was cancelled. Stopping the function.")
return
print("Waited 5 seconds")
Once you call resume, the function state is invalidated. Since your SceneTreeTimer is still executing and trying to resume the function state once more on its timout, you get this error (it tries to resume an invalidated state, so I guess there is some check missing in Godot’s internals). I suggest you use a regular Timer node, which can be canceled.
extends Node2D
var timer = null
func _ready():
# Wait 5 secs for something
_do_stuff()
# Simulate your _on_Button_pressed method by waiting 1 sec
# This has nothing to do with your problem, I'm just too lazy
# To create a button ;)
yield(get_tree().create_timer(1), "timeout")
_cancel_timer()
func _do_stuff():
timer = Timer.new()
timer.wait_time = 5
timer.connect("timeout", self, "_timer_timeout")
timer.autostart = true
add_child(timer)
func _timer_timeout():
print("Waitet 5 seconds")
if timer:
timer.queue_free()
timer = null
func _cancel_timer():
if timer:
timer.stop()
timer.queue_free()
timer = null
print("The yield was cancelled. Stopping the function")
You’re quite right, I thought that since the yield was resumed the SceneTree timer signal would be discarded somehow, but is indeed not the case.
I made a test with another SceneTree timer in other node emitting a custom signal on timeout, If I block that signal from firing once I resume the yield, there’s no errors. I also though about using a proper timer node like you suggested, but I wanted to understand why this wasn’t working.
I checked the documentation to see if there is a way to cancel a SceneTree timer, but as far as I can tell there’s no way to do it. So your method is the best option. Thanks for answering, helped me alot!