godot lambdas do not capture by design
I learned this on stream today. I was trying to interrupt a coroutine by using a lambda:
func foobar():
var stop = false
var stop_callback = func():
= true
stop connect(stop_callback)
stop_signal.
get_tree().create_timer(10).timeout
await
print(stop) # Always false
The idea here is that I wanted to call
foobar
to kick off some animation (like
playing 20 animations with a delay of 0.1 seconds
between each one) and be able to call
stop_signal.emit()
to cancel the
animation (like playing a different animation for
the same objects). However, Godot does
not capture local variables.
Instead, it will copy the value of the local
variable. This means that if you try to modify the
local variable inside of the lambda, it will be as
if you have a new variable with the same name.
I am shocked and horrified, but apparently this is by design.
One way to get around this is to use a variable
which is normally copied by reference, like a
Variant
:
func foobar():
var stop = { "value": false }
var stop_callback = func():
"value"] = true
stop[connect(stop_callback)
stop_signal.
get_tree().create_timer(10).timeout
await
print(stop["value"]) # Either true or false
Sure, that's fine I suppose.