Open andmish opened 1 month ago
Thanks for bringing up this issue. These are valid concerns, and perhaps we can find a solution that satisfies us here. The reason why _exit
is called after a node leaves the tree is that, quite often, a state (or a behavior tree) gets a hold unto some resources in _enter
that it needs to release (as well as signal connections). The problem with re-parenting is that there is no easy way to detect why the node leaves the tree. Godot doesn't differentiate between reparent
and remove_child
. Is it going to be freed? Stashed away back into a pool of available objects? Or re-parented? We don't have an answer to those questions at the time NOTIFICATION_TREE_EXIT
arrives. Historically, we're releasing resources in the _exit
callback in the behavior trees. I was considering overriding reparent
implementation, but sadly in GDExtension it is not currently virtual.
Godot version
v4.3.stable.official [77dcf97d8]
LimboAI version
[60a7670]
LimboAI variant
GDExtension / AssetLib
Issue description
There are a lot of gameplay situations (especially in heavily animation driven games, with animation blends) where re-parenting need to be done during(in the middle) animation or tween and then current state need to be switched to new state at the end of that animation/tween (examples, AI approaching and getting into the vehicle, character controller and ladder states, or some tricks you will want to do using re-parenting for ledge grabbing/moving along states), so re-parenting there now will triggers
_exit()
every time, interrupts the animations/tweens and resets state toinitial state
(which is also can be completely undesirable, as sometimes initial states are here just for init/reset parameters/variables, I know you can redefineinitial_state
before re-parenting, but it's not about it and will just adds more complications). Or even simpler example: characterWalking
forward on platforms and you re-parent character from one platform to another when it steps on new one for some gameplay reason, if you have some logic in theWalking
_exit()
, it will be triggered now every time (interrupting character walking animation, etc. depends what you do here, and also resettinghsm
toinitial state
), it's just weird behavior for a state machine.How to reproduce
After reverts in https://github.com/limbonaut/limboai/pull/226 this example won't work anymore (works in 1.2.2),
reparent
will trigger_exit()
, thenhsm
will beset_active(true)
inNOTIFICATION_POST_ENTER_TREE
again, meaning we will just return toinitial_state
idle
instead of going tocrawl
(obviously, in this example on second loop reparent will be a failure, and we will proceed tocrawl
as needed, but it's unrelated)