Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnimationTree undesired transition delay #52518

Closed
marmitoTH opened this issue Sep 9, 2021 · 16 comments · Fixed by #52555
Closed

AnimationTree undesired transition delay #52518

marmitoTH opened this issue Sep 9, 2021 · 16 comments · Fixed by #52555

Comments

@marmitoTH
Copy link

Godot version

v3.3.stable.official

System information

Windows 10, GLES3, GTX1650

Issue description

AnimationTree transitions have an undesired delay, it takes one frame, and sometimes more than one, for the sprite to change to the next animation. I thought it was a problem related to the game's logic, but it's not, I've been debugging it for hours analyzing the process frame by frame, it's definitely an AnimationTree bug.

Steps to reproduce

To reproduce the bug in a minimal way, I coded a very simple logic. By holding right, the player will start the running animation. By holding space, the player position will offset down by 10 pixels and switch to the rolling animation.

Expectation: The player offsets down and starts playing the animation immediately.
Bug: The player offsets down, waits for one frame and then the animation starts playing.

image

The same behavior also happens when transitioning back to the previous animation.

There's another bug, probably related to this one, but harder to reproduce. It seems like that when one animation is about to transition to another, and I switch to another animation, the last animation being played freezes for several frames before actually changing the sprite. My AnimationTree looks like this (the Xfade Time in both transitions is 0):

image

Minimal reproduction project

animation_tree_bug.zip

@Calinou
Copy link
Member

Calinou commented Sep 10, 2021

cc @TokageItLab

@TokageItLab
Copy link
Member

TokageItLab commented Sep 10, 2021

I remember a similar problem has been reported with StateMachine.

@TokageItLab
Copy link
Member

TokageItLab commented Sep 10, 2021

@marmitoTH @Calinou This issue is caused by the fact that the AnimationNodeTransition::process() is run before the setting properties in the frame. So, the solution is to set the ProcessMode of AnimationTree to Manual and use AnimationTree.advance() in GDScript.

e.g. animation.gd

func _process(delta):
	handle_motion(delta)
	handle_animation()
	$"AnimationTree".advance(delta)

Nevertheless, it might be better to default the animation process() to run at the end of the frame. So, we should discuss this with @reduz in the near future.

cc @lyuma @fire @SaracenOne

@marmitoTH
Copy link
Author

@marmitoTH @Calinou This issue is caused by the fact that the AnimationNodeTransition::process() is run before the setting properties in the frame. So, the solution is to set the ProcessMode of AnimationTree to Manual and use AnimationTree.advance() in GDScript.

e.g. animation.gd

func _process(delta):
	handle_motion(delta)
	handle_animation()
	$"AnimationTree".advance(delta)

Nevertheless, it might be better to default the animation process() to run at the end of the frame. So, we should discuss this with @reduz in the near future.

cc @lyuma @fire @SaracenOne

I've tried it before and didn't work, still have the same issue. Just tried it again and the player still offsets down first before switching the animation but seems to happen only some times. The same bug happens when switching back to the ground animation.

image

Here's a video where you can skip frame by frame: https://i.imgur.com/hPnTdYg.mp4
And here's the updated project: animation_tree_bug.zip

@TokageItLab
Copy link
Member

TokageItLab commented Sep 10, 2021

@marmitoTH You need to change it to Manual.

to set the ProcessMode of AnimationTree to Manual

スクリーンショット 2021-09-10 23 57 47

@marmitoTH
Copy link
Author

@TokageItLab I changed it to Manual, I did exactly what you suggested.
image
image
I guess this is another bug then?

@TokageItLab
Copy link
Member

TokageItLab commented Sep 10, 2021

@marmitoTH If you change _process() to _physics_process(), won't that cause visual problems?

@TokageItLab
Copy link
Member

@marmitoTH Separately above, how about if the AnimationPlayer is also updated using Manual and advance()?

@marmitoTH
Copy link
Author

@TokageItLab It causes the same problem, seems to make no difference at all. I tried with both _process and _physics_process, using Manual for the AnimationPlayer and the AnimationTree. It takes at least one frame to switch the animation, it's inconsistent though, some times the problem doesn't happen (just like I mentioned before and how you can see in the video).

@TokageItLab
Copy link
Member

In the video, the fps was too high to be recognized, but I was able to reproduce the problem by fixing the fps at 5 in the Debug settings. I will investigate.

@ICatRegister
Copy link

In my project, manual advance really switches animations within the current frame, no more one frame delay. However i am using AnimationNodeStateMachinePlayback, not the AnimationNodeStateMachineTransition

@TokageItLab
Copy link
Member

TokageItLab commented Sep 10, 2021

I found one line where the calculation was wrong (#52543). After applying this fix and changing the animation interpolation method to "Continuous" instead of "Discrete", the sample project will transition correctly.

スクリーンショット 2021-09-11 2 36 09

I will have to look into the issue of the different behavior depending on the animation interpolation method, but it may be a problem with the blending of discrete keys.

Edited:
Interpolation with Discrete problem will be solved by #52555.

@TokageItLab
Copy link
Member

TokageItLab commented Sep 10, 2021

This issue will be solved by #52543 and #52555.

@ICatRegister
Copy link

This issue will be solved by #52543 and #52555.

AnimationNodeStateMachine node still has a one frame delay issue

@TokageItLab
Copy link
Member

TokageItLab commented Sep 11, 2021

@ICatRegister Is that a separate issue from using ProcessCallback = Manual & advance()? The two PRs above are for this issue (#52518). For StateMachine, the behavior and implementation are different and we need to proceed in #46798.

@akien-mga akien-mga added this to the 4.0 milestone Sep 20, 2021
@berarma
Copy link
Contributor

berarma commented Sep 21, 2021

I think this is related. If the animation in AnimationPlayer has the loop option enabled, when transitioning from one node to another one in the state machine, it might start replaying the old animation (just the first frame) then switch to the new animation.

Let's say I have a walking animation with loop enabled in AnimationPlayer, when AnimationTree advances from this animation to the idle animation it will play the first frame of the walking animation inbetween. The transition switch mode is AtEnd. It should transition exactly when the animation ends without playing any more frames.

It's like the transition may get delayed for one frame and for this time it keeps playing the old animation. It happens most of the time but not always.

When disabling the animation loop this doesn't happen, I guess it's not noticed, but I think the final frame is still being displayed for two frames before changing to the new animation.

I haven't tried the PRs, I'm trying on 3.4-beta4. I'll try it as soon as there's a new beta release available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants