godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.8k stars 20.91k forks source link

Seeking to looped animation end, actually seeks to beginning. #85220

Open rakkarage opened 10 months ago

rakkarage commented 10 months ago

Godot version

4.2.rc (a34814b0b)

System information

Godot v4.2.rc (a34814b0b) - Ubuntu 23.10 23.10 - Wayland - Vulkan (Forward+) - dedicated AMD Radeon RX 6600 (RADV NAVI23) () - 12th Gen Intel(R) Core(TM) i5-12400F (12 Threads)

Issue description

When you seek with code to end of looped animation it seeks to beginning.

extends Node2D

@onready var _sprite = $Sprite2D
@onready var _animation = $Sprite2D/AnimationPlayer

func _ready():
    _animation.seek(0.9, true)
    _animation.pause()

Fix: https://github.com/godotengine/godot/pull/85186

Steps to reproduce

  1. Create an animation, e.g. for scale
  2. Set length to 0.9 and snapping to 0.1
  3. Add a key at the beginning and end
  4. Enable looping
  5. run code to display last frame. but shows first

Minimal reproduction project

ReproductionProject.zip

akien-mga commented 10 months ago

To clarify as the bug reporting was a bit confusing, maybe just nuance lost in translation:

This is related to #37343, which was specific to what happens from the editor when seeking the timeline to the end. This editor-specific behavior was fixed for 4.2 in #85193. That fix could also be backported to 3.x if wanted.

This issue now advocates for doing the fix in the runtime directly, considering that the same bug is reproducible from script as shown above. The main question is whether this is considered a bug, or intended behavior, by the @godotengine/animation team.

If it's a bug, then indeed a fix such as #85186 may be a better approach than the editor-specific workaround added in #85193.

AThousandShips commented 10 months ago

Note that the proposed fix was rejected by the team, though that would be re-evaluated, if say a new PR should be opened even if the proposed fix is valid, as it'd be more specific

TokageItLab commented 10 months ago

Why the end of the loop animation should not be the first key in the editor is for editing purposes.

In GDScript/runtime, there is a possibility to use seek() to play the animation player with its own delta.

Then, looping animation should loop when it is seeked, and fposmod should work with seek ideally. So is the intended behavior, and not a bug.

If anyone want to create something like AnimationPlayerEditor in GDScript without using tools, it may be necessary to use Hack, but this is a very rare case and should not be a priority.

rakkarage commented 10 months ago
extends Node2D

@onready var _sprite = $Sprite2D
@onready var _animation = $Sprite2D/AnimationPlayer

func _ready():
    _animation.seek(0.9, true)
    _animation.pause()

so this is not allowed/possible? cannot seek to end of any animation?

TokageItLab commented 10 months ago

You should simply turn off the loop.

rakkarage commented 10 months ago

why not allow seek to end of looped animations? like in editor?

TokageItLab commented 10 months ago

why not allow seek to end of looped animations? like in editor?

https://github.com/godotengine/godot/issues/85220#issuecomment-1822920593

rakkarage commented 10 months ago

Why the end of the loop animation should not be the first key in the editor is for editing purposes.

this not say why

In GDScript/runtime, there is a possibility to use seek() to play the animation player with its own delta.

this not say why

Then, looping animation should loop when it is seeked, and fposmod should work with seek ideally. So is the intended behavior, and not a bug.

this not say why

If anyone want to create something like AnimationPlayerEditor in GDScript without using tools, it may be necessary to use Hack, but this is a very rare case and should not be a priority.

this not say why

akien-mga commented 10 months ago

Please be constructive in your comments, as per our Code of Conduct.

I believe Tokage's point is that if the animation is set to loop, then when seeking, it needs to loop when it reaches the end. If it doesn't loop back to the start, then it's not a looping animation. So the questions are:

The current behavior where seeking to the end means triggering the loop probably makes the logic more predictable. Not resetting when seeking to the end would leave the animation in a state that doesn't exist in practice when looping naturally. The end of the animation == the restart of the animation.

TokageItLab commented 10 months ago

While it is easy to understand animation in terms of frames, in a looping animation, the actual processing of the last frame will overlap with the first frame.

The loop section of the animation 1,2,3,2,1,2,3,2,1 is 1,2,3,2, not 1,2,3,2,1, and the last key frame is only needed during editing for interpolation and should not be processed during playback.

rakkarage commented 10 months ago

"should not be processed during playback" seek is not really playback right?

Pingpong works already and can seek to end from code or ui. without any fix. A normal looping animation without pingpong: 12 Can seek to key 2 in editor but not code? Can seek to end of looped pingpong in code but not looped linear in code? just from ui??? Like in the original issue was animating scale from big to small. If I wanna seek to end (smallest) that should work right? It does not.

You could have "solved" the original bug like this too: "You should simply turn off the loop."

rakkarage commented 10 months ago
  • What happens if you seek to the end?
  • If in code pingpong loop seeks to end and linear loop seeks to start. In editor both seek to end now.
  • With this fix both seek to end in code. How can !editor change meaning of "seek to end" for linear only?
  • What happens in the immediate next frame?
  • Continues normally.
  • What happens if you seek beyond the end?
  • From my testing, can't seek past end (just goes to end) from ui or code. Tho animation continues (plays) normally in all cases.
TokageItLab commented 10 months ago

seek is not really playback right?

No. If p_update = true, playback is performed. Also, if the animation seeks beyond the end of the animation, it must loop.

See also https://github.com/godotengine/godot/pull/85225#issuecomment-1823612544.