godotengine / godot

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

AnimationPlayer's blending animation end time are force trimmed by the end time of the last playbacked animation #99486

Open Lutcikaur opened 4 days ago

Lutcikaur commented 4 days ago

Tested versions

Reproducible in : Godot_v4.4-dev4_mono_linux.x86_64 Not reproducible in : Godot_v4.3-stable_mono_linux.x86_64

System information

Godot v4.4.dev4.mono - Pop!_OS 22.04 LTS on X11 - X11 display driver, Multi-window, 2 monitors - OpenGL 3 (Compatibility) - Mesa Intel(R) Graphics (ADL GT2) - 12th Gen Intel(R) Core(TM) i7-12700H (20 threads)

Issue description

It seems that in rolling animations, a default blend time > 0.02 will restart the animation from an odd position instead of correctly lerping to the new animation. It seems to happen with other animations but it is most pronounced with this rolling animation from mixamo.

This is the bug in MRP in v4.4-dev4

https://github.com/user-attachments/assets/32dbe41c-8918-447c-8a25-494ebc52e3fc

This is the same MRP project in v4.3-stable

https://github.com/user-attachments/assets/aa82b997-9af5-4e08-9a6d-9daa8afa43c9

Steps to reproduce

AnimationPlayer > Playback Options > Default Blend Time to something >= 0.02, I first noticed it when set to 0.3s. Play an animation, and on or near its completion, play another animation.

This is the minimally viable reproduction code. It starts playing the roll animation, and at the time roll should be completed, it plays the run animation. the MRP code will loop between both animations to show it better.

extends AnimationPlayer

var timer : float
var triggered : bool

func _ready():
    play("test/roll")
    timer = get_animation("test/roll").length
    pass

func _process(delta):
    timer -= delta
    if timer < 0:
        if !triggered:
            play("test/run")
    pass

Minimal reproduction project (MRP)

animation-bug-test.zip

TokageItLab commented 3 days ago

It is not a bug.

The problem is that because there are xfade on both sides of the roll, then your trying to keep animation length is actually longer than the length of the roll animation.

MRP does the roll first, but the problem should always show up if you do the run first. With these considerations in mind, the length of the correct roll animation should be retrieved by timer = get_animation("test/roll").length - playback_default_blend_time instead of timer = get_animation("test/roll").length; It is necessary to subtract only one of the xfade from the animation length, because after executing play(), AnimationPlayer will already be the state of the next animation and will use the length of that one.

Lutcikaur commented 2 days ago

@TokageItLab

Offsetting by -playback_default_blend_time still causes the error to occur. The timer I set was just to give a solid reproduction of the issue, which I reproduce by calling play("different/animation") at a time near the end of this animation (a roll that causes the model to flip) & it does not blend the same way in 4.4-dev4 as it does in 4.3stable.

A better example of the root issue: Set timer = get_animation("test/roll").length + 0.5 and let MRP run. The roll animation will play to completion, and leave the character skeleton in an upright position for a half second. At that point, Run will play, and character will snap to being upside down, feet in the air, and then spin back into the run animation. My argument is that in 4.3stable when this blend occurs, the upright character blends with much less movement than in 4.4dev4 (minor hand movements compared to doing a somersault)

The code attached to the AnimationPlayer in the original MRP loops between roll and run (but does start with roll). Swapping to run first still causes this to occur on 4.4dev4 and not occur on 4.3stable.

This does seem like a regression because with this behavior in 4.4dev4 i cannot reliably blend a playing animation into a given animation by setting default blend time and calling animation.play(), which worked in 4.3stable

Thank you.

TokageItLab commented 2 days ago

I have looked at the MRP again and they are the same in 4.3stable and 4.4. If you still have a issue, then resend an MRP that behaves differently in each.

TokageItLab commented 2 days ago

Oh, I see the problem with the latest one. So the hitch in the MRP is not a problem. It would be helpful if you could attach a video comparing 4.3 and 4.4 to the summary and add a note to clarify what the problem is. Perhaps I guess that it is the regression by https://github.com/godotengine/godot/pull/91765. I will take a look at it later.

Lutcikaur commented 2 days ago

There are two videos under Issue Description that show the issue occuring. In each of those clips, it is one play() to roll, one play() to run. The 'roll' animation was already called before the videos start. The "run" animation is called once near the middle of the clips.

The MRP behaves very differently for me in 4.4dev4 versus 4.3stable, both from fresh projects and when swapping the same mrp project between 4.4d4 and 4.3s

I have now attached a third clip to this comment showing the full editor launch sequence (4.4dev4 first, then into 4.3stable). in this clip i added a half second timer to the delay when switching animations and set engine time scale to 0.7 to see it in a bit slower motion. it is set on a 0.3s blend time. It makes it a bit clearer whats going on.

The roll animation itself starts in a running pose, crouches to the ground, rolls forward, stands back up, and re-assumes the running pose.

In 4.4dev4 the character performs the roll animation to completion, pauses, and when run is played, the character model snaps into a crunched position with feet in the air, their back towards the ground. The model then lerps, moving their feet towards the ground, body towards the correct current running position, and then the running animation continues as normal after the 0.3s lerp.

The animation essentially performs its roll, waits, then re-performs a mangled 70% of its roll in 0.3s, and then continues the run.

In 4.3stable the character performs the roll animation to completion, pauses, and when run is played, the characters arms and legs perform a small lerp to the run animations starting position, and the character is running correctly.

https://github.com/user-attachments/assets/3237e825-fbed-41d2-b8c4-81c0a2b205fd

Thank you again.

TokageItLab commented 1 day ago

I have sent #99585 as the fix, please check it if you can.

Lutcikaur commented 1 day ago

With that build, the MRP works correctly 👍. I will try to get .net building and test it with my project where i saw the issue originally occur.

Thanks a ton.