diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 1cba9953664..a1b53346d87 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -146,7 +146,7 @@ Sets the number of times the tweening sequence will be repeated, i.e. [code]set_loops(2)[/code] will run the animation twice. Calling this method without arguments will make the [Tween] run infinitely, until it is either killed by [method kill] or by freeing bound node, or all the animated objects have been freed (which makes further animation impossible). - [b]Warning:[/b] Make sure to always add some duration/delay when using infinite loops. 0-duration looped animations (e.g. single [CallbackTweener] with no delay) are equivalent to infinite [code]while[/code] loops and will freeze your game. + [b]Warning:[/b] Make sure to always add some duration/delay when using infinite loops. 0-duration looped animations (e.g. single [CallbackTweener] with no delay or [PropertyTweener] with invalid node) are equivalent to infinite [code]while[/code] loops and will freeze your game. If a [Tween]'s lifetime depends on some node, always use [method bind_node]. diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 53ff3eeeae1..a2fed718bee 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -283,6 +283,10 @@ bool Tween::step(float p_delta) { float step_delta = rem_delta; step_active = false; +#ifdef DEBUG_ENABLED + float prev_delta = rem_delta; +#endif + for (Ref &tweener : tweeners.write[current_step]) { // Modified inside Tweener.step(). float temp_delta = rem_delta; @@ -312,6 +316,12 @@ bool Tween::step(float p_delta) { start_tweeners(); } } + +#ifdef DEBUG_ENABLED + if (Math::is_equal_approx(rem_delta, prev_delta) && running && loops <= 0) { + ERR_FAIL_V_MSG(false, "Infinite loop detected. Check set_loops() description for more info."); + } +#endif } return true;