Description
Tested versions
I've tested the following Godot version:
- v4.0.stable.official [92bee43] (works)
- v4.1.stable.official [9704596] (works)
- v4.1.1.rc1.official [e709ad4] (immediate warning)
- v4.1.1.stable.official [bd6af8e] (immediate warning)
- v4.2.1.stable.official [b09f793] (immediate warning)
- v4.2.2.rc1.official [c7fb064] (immediate warning)
- v4.2.2.rc2.official [c61a686] (immediate warning)
- v4.2.2.rc3.official [16a8334] (delayed warning)
- v4.3.dev6.official [89850d5] (delayed warning)
System information
Godot v4.3.dev6 - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 Ti (NVIDIA; 31.0.15.5222) - Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz (8 Threads)
Issue description
An AnimationTree
with a state machine and only two states/animations that use transitions with advance_mode
set to "auto", will report a "_transition_to_next_recursive" warning if the advance_expression
allows transition, even if the switch_mode
is set to "At End".
Going from "idle" to "fire" happens when the advance_expression
of triggered
evaluates to true. This is driven by a simple button press in the UI:
Going from "fire" back to "idle" uses the expression not triggered or automatic
.
If automatic
is true, this results in "automatic fire", continuously switching between the "idle" and "fire" states/animations, and works as expected.
Main:<CanvasLayer#28168946939>::_fire() -> pew pew! (1983)
Main:<CanvasLayer#28168946939>::_fire() -> pew pew! (2750)
Main:<CanvasLayer#28168946939>::_fire() -> pew pew! (3516)
Godot still prints the warning:
W 0:00:02:0237 _transition_to_next_recursive: AnimationNodeStateMachinePlayback: parameters/playback aborts the transition by detecting one or more looped transitions in the same frame to prevent to infinity loop. You may need to check the transition settings.
<C++ Source> scene/animation/animation_node_state_machine.cpp:909 @ _transition_to_next_recursive()
This was originally introduced by PR 79141: Fix infinite loop state check in AnimationStateMachine
in 4.1.1-rc1 and would print an immediate warning.
PR 89575: Move the line of infinity loop checking in AnimationStateMachine added in 4.2.2-rc3 modified the behavior, and the warning is only printed if the button is held down.
It seems the recursion detection doesn't take the switch_mode
"At End" into consideration.
The issue can be "worked around" by introducing an intermediate state/animation ("trigger") and updating the advance_mode
for the transitions to use that one instead:
It also doesn't occur if the idle transition is set to "At End":
However, that means the "idle" animation has to be very short for it not to delay the switch back to "fire".
Previous related issues:
- issue Spurious animation transition warning: "aborts the transition by detecting one or more looped" for
switch_mode = at_end
#82935: Spurious animation transition warning: "aborts the transition by detecting one or more looped" forswitch_mode = at_end
- issue AnimationTree abort transition to stop infinite loop #89520: AnimationTree abort transition to stop infinite loop
Steps to reproduce
The MRP is setup to reproduce the issue. Hold down the "fire" button (brief button presses will not trigger it in 4.2.2-rc3 and later) to see the warning
Minimal reproduction project (MRP)
The MRP repository: animation_tree_transition_issue.
The MRP sets up a minimal AnimationTree
state machine entirely controlled by the transitions' advance_expression
.
The transitions' advance_mode
is always set to "auto".
It's a firing mechanism for a gun, using triggered
and automatic
properties as part of the advance_expression
.
The state machine defaults to the "idle" state/animation, until the triggered
property results in a transition to the "fire" state/animation.
If the trigger is released or automatic
is true
, the state will transition back to "idle".
Holding down the "fire" button in the UI will repeatedly print "pew pew".
This functionally works but results in a _transition_to_next_recursive
warning printed by Godot starting with 4.1.1-rc1.
A change introduced in 4.2.2-rc3 results in the warning only if the button is pressed for longer.