Godot Version
4.4.1
Question
I have a scene with a cube. The following script is attached:
extends Node3D
func _process(delta: float):
rotate(Vector3.FORWARD, PI / 4 * delta)
rotate(Vector3.RIGHT, PI / 6 * delta)
rotate(Vector3.DOWN, PI / 8 * delta)
This works as expected, and all modifications appear instantly with hot reload. Now consider this version that stores the operations in a Callable
:
extends Node3D
var _operations: Array[Callable] = []
func _ready():
_operations.append(func(delta: float): rotate(Vector3.FORWARD, PI / 4 * delta))
_operations.append(func(delta: float): rotate(Vector3.RIGHT, PI / 6 * delta))
_operations.append(func(delta: float): rotate(Vector3.DOWN, PI / 8 * delta))
func _process(delta: float):
for operation in _operations:
operation.call(delta)
This Callable
version does allow for numerical changes (like PI / 4
to PI / 2
) to work with hot reload - but adding or removing operations in _ready
will cause Godot to throw the following error in operation.call(delta)
:
Attempt to call function '<invalid self lambda> (Callable)' on a null instance.
My understanding is that the custom lambda created in _ready
now belongs to an invalid object - and indeed, operation.is_valid()
properly returns false. My question is: how can I nonetheless keep the stored Callable
behavior even when it becomes invalid?
My initial thought was that swapping out the underlying self
instance would fix it, but there’s no such operation in GDScript - bind
is only for explicit parameters. Similarly, I thought of just passing an initial parameter containing self
, and using it inside each Callable
, but this still triggered the error.
Is there any way to fix or adjust a Callable
so that it may continue to function after a hot reload? Or to clarify further, how can I adjust the Callable
version so it doesn’t throw when I comment out a line, and properly picks up the new line when I comment it back in?