godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.08k stars 69 forks source link

Add a way to loop one section of an animation in AnimationPlayer #2159

Open zextillion opened 3 years ago

zextillion commented 3 years ago

Describe the project you are working on

I'm working on a 2D action-platformer.

Describe the problem or limitation you are having in your project

There are animations I have that loop, but have a start-up animation. Right now with the way I've implemented animations, if I loop an animation, it will also loop to those initial few frames of the start-up animation.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Being able to set a loop section will allow the both the start-up frames to play and loop just the specified section.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

If the animation has looping enabled, a bar will pop up over the timeline with two endpoints. The time range inside the bar gets looped. The default values are starting at 0.0 seconds and ending at how long the animation is, and the user can drag the endpoints elsewhere in the animation.

If this enhancement will not be used often, can it be worked around with a few lines of script?

I already work around this by making another animation and having the AnimationPlayer automatically transition to that loop animation when the start-up animation ends.

Is there a reason why this should be core and not an add-on in the asset library?

A feature similar to this already exists when looping audio files, and it gives the user more flexibility when creating animations inside of the engine.

Calinou commented 3 years ago

You can already do the following:

# `start` is a non-looping animation. `loop` is a looping animation.
$AnimationPlayer.play("start")
$AnimationPlayer.queue("loop")
robertarnborg commented 1 year ago

This could be used similarly to Fmod loop sections for adaptive audio too.

GigglingGalaxy commented 3 months ago

This would be great. Common use case #8526 too?: waving once while walking/running (lots of forum q&a about this and rn have to basically rig it in using advanced animation techniques in Godot or Blender). + any longer animation that we only want part of to play while still walking (or doing any loop animation).

Maybe a Bonus to this feature: one non-loop track takes priority over other looping track(s) (ie the bones of walking that are also used in the "wave hello" basically pause in their loop while "wave hello" track plays once)? Maybe track closest to top takes priority automatically if same bones involved? The "wave hello" track would be able to be set inactive -> active on wave input without ever stopping the walk or needing a tree? Win: people who aren't anim pros can "rig" a running wave hello (or any non-loop part of their loop animation) without getting into deep Blender level stuff.

Bonus 2: Might allow for some really cool things with CPU particles, too!

My weird use case: I'm not sure if this feature will help, but when running movement from physics, keeping the physics movement active while a movement/progress animation is playing. I need to animate remote path progress once AND want character playing walking animation looped the whole time. Easily done with 2 animation players (one in scene, one on character) but then my "can look at target" in physics of character stops working altogether. If I could loop the walking track(s) but not path progress track rather than loop both. It's actually fine rn because the progress takes 30 seconds so setting stop() at end (before the progress track would actually hit loop point) works fine. I am probably missing something with my "can look at target" so maybe this is not a good use case, just wanted to clarify how I got to this thread.

willdayble commented 3 months ago

100% love this idea. Would be as simple as setting start and start points on the looping section, by default the entire thing.

<3

TheWarmWaffle commented 3 weeks ago

You can already do the following:

# `start` is a non-looping animation. `loop` is a looping animation.
$AnimationPlayer.play("start")
$AnimationPlayer.queue("loop")

I think this function works well combined with the ability to call functions in the animation player itself, in other words add a keyframe that queues the loop animation in the middle of the start animation through the AnimationPlayer.

Edit: Unfortunately it doesn't work well with the AnimationTree, as it glitches out with queued animations apparently.

TheWarmWaffle commented 2 weeks ago

https://github.com/godotengine/godot-proposals/discussions/10138#discussion-6904841