I had the exact same issue. Took me some hours to get a workaround which doesn't require you to change all your yield's. Create a new singleton and paste this code:
func yield_wait(var timeout : float, var parent = get_tree().get_root()):
var timeoutCap = max(0, timeout / 1000.0)
if timeoutCap <= 0:
return
var timer = Timer.new()
timer.set_one_shot(true)
# ensure that the timer object is indeed within the tree
yield(yield_call_deferred(parent, "add_child", timer), "completed")
timer.start(timeoutCap)
var timerRoutine = _yield_wait(timer)
if timerRoutine.is_valid():
yield(timerRoutine, "completed")
yield(yield_call_deferred(parent, "remove_child", timer), "completed")
func _yield_wait(var timer : Timer):
yield(timer, "timeout")
func yield_call_deferred(var node, var action, var parameter):
node.call_deferred(action, parameter)
yield(get_tree(), "idle_frame")
Now you can call, like before:
yield(yourgd.yield_wait(5000, self), "completed")
to wait for 5 seconds. (I used MS, since I dont like seconds)
The magic is simple: The code attaches a timer node to the caller. When the nodes gets queue_freed, then the timer node also will be removed. Thus, its promise (timer.create(...)) won't wait till its end, but abort and return to your code.