• RuntimesUnityBugs
  • Spine upgrade to AnimationState.cs leads to different animation behavior

Hi,

We were updating our project to Unity 6 and, after update to Unity 6 we also tried upgrading spine (C#) runtime from 4.2.31 to 4.2.34 (The issue might not be related to Unity 6)

This spine upgrade is causing the editor and build to freeze after a while without giving any specific error.
I don't have an isolated project, but I isolated the code change that is causing the issue. Maybe you could guess what is wrong just from the code?


This is the change that is causing the issue.

Related Discussions
...

It seems like the issue you're experiencing with the Spine upgrade causing the Unity editor and build to freeze might be related to a specific change in the AnimationState.cs file. Unfortunately, without more detailed information or an isolated project, it's challenging to pinpoint the exact cause of the problem. However, based on similar issues discussed in the forums, it could be related to a bug or an incompatibility introduced in the newer version of the Spine runtime. You might want to check if there are any known issues or updates related to the version you are using on the Spine GitHub issues page. Additionally, ensure that all other dependencies and configurations in your project are compatible with the new Spine runtime version.

@abuki Sorry to hear you're having troubles. Note that if you are using the spine-unity runtime, you need to update the spine-csharp core and spine-unity runtimes at the same time. Which version of the spine-unity runtime were you using before and after the update?

This spine upgrade is causing the editor and build to freeze after a while without giving any specific error.

What do you mean by "after a while"? When building (to what platform?), or when opening your project after the update, or when having the project open and after updating the runtime? Please always provide as much information as possible.

In general we need a reproduction project to fix such issues unfortunately.

Spine-csharp: 4.2.31 -> 4.2.34
Spine-unity: 4.2.87 -> 4.2.95
(as stated in package.json)

Old Package version: spine-unity-4.2-2024-09-23.unitypackage
New Package version: spine-unity-4.2-2025-02-05.unitypackage

I am always upgrading using this package https://esotericsoftware.com/spine-unity-download, I assume it updates both spine-csharp and spine-unity, right?

After a while means you start the game, the game runs for a while and then freezes. I guess there is some infinite loop because no errors, no crash. It could be a problem with our scripts somehow, but was working OK before the upgrade. Extracting reproduction project would probably be very time-consuming in this case. That is why I was asking if there is any possible visible change in the code above that could be causing the problem. But I barely understand what this piece of code should do.

  • Harald님이 이에 답장했습니다.

    No rush, we can stay on the old runtime for a while. Just want to be sure we are future-proof 🙂

    • Harald님이 이에 답장했습니다.

      abuki I am always upgrading using this package https://esotericsoftware.com/spine-unity-download, I assume it updates both spine-csharp and spine-unity, right?

      Yes, you assume correctly. The unitypackage is released manually with compatible combinations of spine-csharp and spine-unity only.

      After a while means you start the game, the game runs for a while and then freezes.

      So I assume you mean your game freezes both in the Unity Editor after entering play mode after some time as well as in the built executable, right?

      Extracting reproduction project would probably be very time-consuming in this case.
      That is why I was asking if there is any possible visible change in the code above that could be causing the problem.

      Showing us the code changes that trigger your issue helps a bit, but the changes are there for a reason. In this case to fix issues when adding animations without advancing time but still triggering an update call (AnimationState.Update). Previously this could lead to a stack overflow, which is fixed by the above changes.

      Unfortunately the relevant other part is your project setup and code which triggers your issue. I'm afraid we can't fix the issue without being able to reproduce it or understand what you are doing. We would love to fix any hidden issues or prevent potential problems, so if you could sometime in the future try to strip your problematic project down to just the problematic parts, that would be a great help.

      • abuki님이 이에 답장했습니다.

        abuki No rush, we can stay on the old runtime for a while. Just want to be sure we are future-proof 🙂

        That's good to hear. Nevertheless, if you could in the future find the time to strip the project down to a minimal reproduction project, please do send it to us as a zip file via email to contact@esotericsoftware.com (briefly mentioning this forum thread so that we know the context).

        Harald So I assume you mean your game freezes both in the Unity Editor after entering play mode after some time as well as in the built executable, right?

        Yes.

        I will try to look at it more deeply or to isolate the problem next week. Thanks for pointing out what the changes do, that might help.

        • Harald 님이 이 게시물을 좋아합니다..
        5일 후

        Harald In this case to fix issues when adding animations without advancing time but still triggering an update call (AnimationState.Update). Previously this could lead to a stack overflow, which is fixed by the above changes.

        Strange, I fixed the issue by replacing SkeletonAnimation.Update(0); with SkeletonAnimation.AnimationState.Update(0); in one of our scripts.

        Can you tell me the design difference between these methods? Which one should I be using?

        In my specific case, I am subscribed to animation start event and starting another animation on a different track but can see one frame missing attachment. The Update(0) did the trick to see the change immediately, the same frame - that's why I am calling it. I see I am using the SkeletonAnimation.Update(0); in many other scripts without problem (probably? not checked all), but now I am unsure if it's safe, and what is the correct use case?

        • Harald님이 이에 답장했습니다.

          abuki Strange, I fixed the issue by replacing SkeletonAnimation.Update(0); with SkeletonAnimation.AnimationState.Update(0); in one of our scripts.

          Can you tell me the design difference between these methods? Which one should I be using?

          There is quite a big difference. SkeletonAnimation.Update includes AnimationState.Update, but many more things.

          AnimationState.Update(0) just updates the core AnimationState and triggers animation-driven callback events, but does not appy the updated animation state to the Skeleton, does not issue callbacks like UpdateLocal, UpdateWorld, UpdateComplete and does not adjust Unity-specific things like updating the Mesh.

          You can also check out the SkeletonAnimation.Update(float deltaTime) source code here.

          abuki I see I am using the SkeletonAnimation.Update(0); in many other scripts without problem (probably? not checked all), but now I am unsure if it's safe, and what is the correct use case?

          It is in general "safe" and normal to call SkeletonAnimation.Update(0). It can however become problematic if you e.g. create hidden infinite loops through circular callbacks (A calling B calling C calling A again) or something like that. I would recommend to attach a debugger and pause in the debugger when the editor is getting stuck. Also you could have a try removing your own custom components bit by bit until the issue no longer occurs, to get a clue how the issue is triggered.

          6일 후

          Hi Harald,

          Thanks for the detailed info. I found the issue in our codebase and fixed it, unifying the calls to Update(0) across the whole project.

          The strange thing is that the runtime update revealed the problem, even though it had been working for a long time before. But now I see the issue clearly—I was just misled into thinking it was caused by the Spine runtime update.

          • Harald 님이 이 게시물을 좋아합니다..

          Glad to hear you've figured it out, thanks for letting us know!

          13일 후

          Hi Harald,

          Unfortunately, we discovered a new problem again related to this piece of code that was upgraded. It was not obvious on the first view, as it appears in some specific cases. As before, it is very challenging to share repro project, but I will try to explain what we see again as you might guess if that is in your code or mine.

          We have a fairly complex track setup for the main characters, playing multiple animations in different tracks. And now it looks like when on one track the animation is interrupted and mixed to another that does not have keys for the bone the previous had, the pose for the bone is kept instead of mixing to the setup pose. Which should be the correct behavior, right?

          Tl;dr I see visual changes in played animations with the same animations/track then before the update. I guess spine runtime should be consistent in interpreting animations after update, right?

          Before we can be sure the behavior is consistent, I am downgrading back to an older version of spine runtime, which works fine (I kept the cleanup of my code, which was good anyway).

          • Harald님이 이에 답장했습니다.

            You can also update the discussion title of this to something like:
            "Spine upgrade to AnimationState.cs leads to different animation behavior"

            Harald님이 제목을 Spine upgrade to AnimationState.cs leads to different animation behavior(으)로 변경했습니다. .

            abuki We have a fairly complex track setup for the main characters, playing multiple animations in different tracks. And now it looks like when on one track the animation is interrupted and mixed to another that does not have keys for the bone the previous had, the pose for the bone is kept instead of mixing to the setup pose. Which should be the correct behavior, right?

            If two animations are on the same track, then mixing out an animation by starting another one will mix out the changes of this animation if there is no key in the second animation. If there are animations on lower tracks, it's not mixed to the setup pose but the lower track will show. It's the same with the empty animation, which has no keys and mixes out the preceding animation, but does not apply the setup pose (which would be strange, overriding everything on lower tracks). If you want to mix to the setup pose on higher tracks overriding lower ones, you need to set a key identical to the setup pose, and have Animation clean up disabled in the export settings (otherwise these setup-pose keys will be removed again automatically during export).

            abuki Which should be the correct behavior, right?

            This sentence was a bit ambiguous. What do you assume to be the correct behaviour?

            • Nate님이 이에 답장했습니다.

              Harald have Animation clean up disabled in the export settings (otherwise these setup-pose keys will be removed again automatically during export).

              Or check Layered!

              • Harald 님이 이 게시물을 좋아합니다..

              Thanks for explaining.

              It rises some questions, but if there is a detailed documentation for this, please give me the link, but I am unsure if I was able to find it.

              To understand it properly, let's have the following example:
              We have a bone A, animations1-3 and 3 tracks.
              Track 0 - empty or unset (in our case, several empty tracks waiting for specific animations)
              Track 1 - animation1 that animates bone A (has keys for A) which is interrupted in the middle, mixed to other animation2 which has no keys for A
              Track 2 - another third animation3 that has no keys for A

              What is the correct and expected behavior? After the mixing, should bone A have keys from setup or from interrupted animation1 (depending on when we started mixing)?

              And please note that from my observation, this behavior changed with the previous code change in the first post. And that what I see in Spine Preview (trying to simulate something very similar) is different from the Unity runtime. There is still a small chance that something is bad in my code, but as I said it was working ok before runtime update. Also I need to be sure what is the correct behavior before diving deeper.

              Another edge case might be what happens when on track 1 or 2 happens mixing during mixing, or calling update or anything special like that (there are some cases like this, difficult to simulate in Spine editor preview). May I ask if you have any test projects for testing these layering cases? Maybe I can try it on them?

              Didn't know about the Layered tick box! That sounds very useful, can you please share a more detailed info or docs link on it?

              • Harald님이 이에 답장했습니다.

                abuki It rises some questions, but if there is a detailed documentation for this, please give me the link, but I am unsure if I was able to find it.

                See:
                https://esotericsoftware.com/spine-applying-animations
                More specifically:
                https://esotericsoftware.com/spine-applying-animations#Tracks
                https://esotericsoftware.com/spine-applying-animations#Playback
                https://esotericsoftware.com/spine-applying-animations#Empty-animations

                abuki What is the correct and expected behavior? After the mixing, should bone A have keys from setup or from interrupted animation1 (depending on when we started mixing)?

                "Track 2 - another third animation3 that has no keys for A" is irrelevant for bone A.
                If the lower tracks don't key bone A as you've mentioned, and you're mixing-out the animation on track 1 which keys bone A to an animation which does not, you should end up with the setup pose.

                If this is not your result, you might have discovered a bug. Could you please describe what result you get? Unfortunately it's a bit ambiguously written.

                abuki Didn't know about the Layered tick box! That sounds very useful, can you please share a more detailed info or docs link on it?

                When selecting an animation in the Tree view, you have options Export and Layered.

                • abuki님이 이에 답장했습니다.