• RuntimesUnreal
  • Animation gets stuck between poses after BeginPlay only

This is an odd one.

I have Idle play automatically on BeginPlay, but then any animation that I transition to (either Walk or Run in my case) gets "stuck" when it's supposed to go back to Idle. The character basically freezes mid-walk and then does the Idle animation but with the legs mid-stride, if that makes sense.

Once you "break out" of this though by going back and forth between a couple more animations it goes back to normal and can't be reproduced during the rest of the play session.

The only thing that's ""fixed"" it is by swapping animations at the start of BeginPlay with some Delays before going into my state machine to do the actual animation transition logic. I don't know why that works but it does.

Does anyone have an idea for a non-hacky way to actually fix this? I don't think it's the actual transition logic because I've tried it three different ways and they all do this, so I must be missing something. It seems to have something to do with the mixtimes between animations, but ONLY ONCE after the game starts and never again. Any help appreciated!

    Related Discussions
    ...

    Versy When a skeleton's animation gets stuck, it is often due to the animation being repeatedly re-set on the same track.
    From the screenshot you provided, it is unclear exactly how this occurs, but you may be able to work around it by inserting a Branch node.

    For example, as shown below, the Spine -> Animation -> Get Current node retrieves the TrackEntry for a specific track, and the Spine -> Track Entry -> Get Animation Name node obtains the animation name. If the retrieved animation name does not match the next animation to be set, the Set Animation node will be executed:

    Could you try ensuring that the same animation is not set consecutively to see if that clears the stack?

      Misaki

      SetAnimation shouldn't be getting called every tick, no. I currently have SetAnimation only being used On State Begin in my state machine, and then bools controlling whether it can transition to the next state, which are also only in On State Begin.

      I don't think it's setting the same animation every frame (I did make that mistake in the beginning) since that results in the animation being stuck on frame 1. With this problem, as you can see from my video below, it will start to play Walk when the character moves, but then if Walk is let go, it plays Idle "on top" of the frame that Walk stopped on.

      Setting all animation mixtimes to 0 stops the problem. But, of course, that's not a solution.

      Again, you can see eventually after a few animation transitions the problem stops. Which is why my "hack" is to just do that a few times at BeginPlay, and then all animations work fine. It's not a "real" solution though, I just am not sure what's going on.

        Versy Thanks for the additional clarification. It certainly looks like this is not a problem with the animation being applied repeatedly, but rather a problem with poses that should be reset not being reset. Could you please email us a minimal UE project that can reproduce this problem?: contact@esotericsoftware.com
        Please include the URL of this forum thread in the email so we know the context. Then we can take a look at what's wrong.

          Misaki Alright, slightly embarrassing, but I've isolated the problem to a modification to SpineSkeletonAnimationComponent.cpp that I had someone do for me in order to get a specific framerate on my animations. I thought to check this before but completely forgot.


          I'm not the coder, but I believe what this is doing is only updating the skeleton on a lower interval instead of deltaTime, to mimic a low framerate. But that is likely causing updates to be "caught" in the middle.

          I know this is probably out of your support range because it's a modified feature, and I assume a faux "framerate" option like this isn't planned to be added to the runtime, so if you have any idea if there's a way to get this to play nice with the skeleton update please let me know! 🙏

            Versy I'm glad you were able to narrow down the problem to some extent! However, the code you showed us does not seem to be wrong, would you still be willing to email us a minimal UE project that can reproduce the problem? Then we can look into it in more detail.

              4 jours plus tard

              Misaki Sure thing I'll do that now! I put the code in your Spine example project file and it produces the same issue. Thank you for looking into it!

                Versy Thanks for providing the UE project files! I wasn't sure at what level you were supposed to check, so I just wanted to make sure I was correct that the behavior you see in the following video is the problem you're encountering?:

                The procedure to reproduce this is to press the H key to make Spineboy walk to the left for a moment, then release the H key.
                Some of Spineboy's poses will then be incorrect, but the idle animation itself seems to be applied, and you can see that some bones are animated correctly.

                As far as I could tell from several attempts, this problem did not seem to occur all the time, just occasionally. It certainly seems to be a problem with the mix, as you mentioned that if you set the mix time to 0, this problem does not occur. Once we can confirm that this is the problem you are experiencing, we will investigate the cause.

                  Misaki Yes that's correct! Apologies I meant to mention the level. This is indeed the issue I'm experiencing. Please let me know if you figure out the cause!

                    Versy Thank you for your response! Our runtime development team is currently engaged in high-priority tasks, and we anticipate that investigating this issue may take some time. We will provide an update in this thread as soon as we have further information.

                      Misaki Thank you, and that's totally fine. I have my strange "workaround" for now, and plenty of other things to work on. Cheers!

                        6 jours plus tard

                        Versy

                        It took long, but we finally should have discovered the issue. There is a fix to port to C/C++ runtimes that we still have in our queue. Here you can find the GitHub issue.
                        You can manually port it, or just wait until tomorrow when I will port it. But you'll need to copy it to your project eventually.

                        There's an additional consideration. Now that you are reducing the framerate, you could consider skipping updates where delta is 0. There are currently consecutive state and skeleton update invocations when Step is 0, leading generally to a waste of resources. If you place:

                        if (Step <= 0.0f) return;

                        in your code, you won't have the issue you reported even if you don't port the fix if you return when Step <= 0.0f.

                        Little update, we've just ported the fix 🙂

                          Davide

                          Thank you so much for the update and the advice!

                          I downloaded the new runtime and copied my code over to SpineSkeletonAnimationComponent.cpp again, but now the animation speed itself slows down, not the "framerate". Even without the if (Step <= 0.0f) return; it's doing this.😟 A bit hard to tell from the GIF but it's just playing all frames in slow-motion now, not skipping frames.

                          Did something change significantly in this update that changes the way the animations play so that the code I have won't work anymore?

                          If it's perhaps an oversight on my end please let me know!

                            Versy

                            Are you sure you didn't make any other modifications to our runtime? The fix we implemented is in the spine-cpp runtime, which is a requirement for spine-ue and should be manually copied as described in step 6 of the Installation paragraph in the spine-ue guide.

                            If you've done all of the above, I need to ask you to again send over a project that reproduces this issue, as I cannot reproduce the slow motion problem you're experiencing on your end.

                            Versy

                            I’ve been thinking more about your code, and I suspect the slow motion you’re experiencing might be caused both by your implementation and potentially by your machine.

                            When you calculate Step like this:

                            Step = Accumulate - FMath::Fmod(Accumulate, ActualFPS);

                            If, for any reason, Accumulate exceeds twice the ActualFPS, you’re only advancing your timeline by one step, when in fact you should be advancing it by two steps.

                            I also remembered we have a Unity example that does something similar here. I adapted the logic to C#:

                            float Step = DeltaTime;
                            if (bDisableInterpolation)
                            {
                            	Accumulate += DeltaTime;
                            
                            	const float FrameDeltaTime = 1.0f / DiscreteFPS;
                            	constexpr int32 MaxFrameSkip = 5;
                            	int32 FramesToSimulate = 0;
                            
                            	while (Accumulate >= FrameDeltaTime)
                            	{
                            		FramesToSimulate++;
                            		if (FramesToSimulate > MaxFrameSkip)
                            			break;
                            
                            		Accumulate -= FrameDeltaTime;
                            	}
                            
                            	if (FramesToSimulate == 0)
                            		return;
                            
                            	Step = FramesToSimulate * FrameDeltaTime;
                            }

                            The MaxFrameSkip should prevent steps from getting too large.

                            Let me know if this version works better.

                              18 jours plus tard

                              Davide

                              Hello again! Sorry for the gap in response, had to step away from dev for a bit. Got a chance to test this.

                              So, good news and bad news after some further testing... The good news is as you said

                              if (Step <= 0.0f) return;

                              seems to fix the animation mixing problem. I didn't actually realize that fix worked because I was using the updated runtime you mentioned, which is causing this slowdown issue.

                              I discovered if(step) only works on my older version of the runtime. And on the newer version you mentioned, this code actually seems to CAUSE the slowdown (at least on my PC as you reported it's not reproducible). And I realized my disable interpolation code doesn't work at all on the new plugin version for some reason.

                              I did some more tests with the exact same project file (the spine-ue demo I grabbed from the updated runtime folder):

                              Old plugin / Modded w/ my original code: my original issue exists ❌
                              Old plugin / Modded w/ (if (step) return): everything works ✅
                              New plugin / UNmodded : no slowdown, but obviously no disabled interpolation ✅
                              New plugin / Modded w/ my original code: disable interpolation doesn't work, BUT no slowdown ❌
                              New plugin / Modded w/ (if (step) return): disable interpolation doesn't work, slowdown ❌
                              New plugin / Modded w/ your code in latest reply_: disable interpolation doesn't work, slowdown ❌

                              So both if(step) and that new code you sent both cause slowdown, but my old code doesn't do anything at all.

                              Here are my PC specs if you think that might matter:

                              Since the code you sent works on the old plugin I'll use that for now, I'm not anywhere near release so it's not a huge issue at the moment for testing. But, of course, this will be an issue in the future with updating. If you have any idea what may be going on with the new one please let me know! Hopefully I'm not overlooking something simple lol. I'm happy to send any files or projects over and I appreciate your looking into this.

                                Versy

                                Your computer is a beast, so that’s definitely not the issue. It might have been a problem if it were a slower machine.

                                There must be some difference in our configurations. I even asked @Misaki to test the latest version of the plugin, and everything works correctly for her as well.

                                Are you sure you're recompiling the plugin after making changes?

                                What’s suspicious to me is this part:

                                Versy New plugin / Modded w/ my original code: disable interpolation doesn't work, BUT no slowdown ❌

                                But disable interpolation should work with the new plugin and your original code!

                                Also, make sure to check the value of the Discrete FPS field under SpineSkeletonAnimation in the Unreal Engine UI.