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():
stop = true
stop_signal.connect(stop_callback)
await get_tree().create_timer(10).timeout
print(stop) # Always falseThe 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():
stop["value"] = true
stop_signal.connect(stop_callback)
await get_tree().create_timer(10).timeout
print(stop["value"]) # Either true or falseSure, that's fine I suppose.