• Runtimes
  • Problem with the anim change.

When I have two anim to play. I play the anim1 and anim 2 was inserted before anim1 started playing or anim1 pay halfway through, but the anim2 occasionally unable to play properly.Is there a way for the subsequent animation to be interrupted and the previous animation to always play normally? I use the "skeletonAnimation.state.SetAnimation()" play the anim.

To ensure that the subsequent animation (anim2) does not interrupt the previous animation (anim1) and that anim1 always plays normally, you can use the AnimationState.AddAnimation() method instead of SetAnimation(). This method queues the animation to play after the current animation completes. Here is an example of how you can achieve this:

skeletonAnimation.state.SetAnimation(0, "anim1", false); // Play anim1
skeletonAnimation.state.AddAnimation(0, "anim2", false, 0); // Queue anim2 to play after anim1

If you need to interrupt the subsequent animation and ensure the previous animation plays normally, you can use the ClearTrack() method to clear the track before setting the new animation:

skeletonAnimation.state.ClearTrack(0); // Clear any queued animations
skeletonAnimation.state.SetAnimation(0, "anim1", false); // Play anim1

Additionally, if you encounter issues with animations not playing correctly due to timing, you can manually update the animation state to ensure it is applied immediately:

skeletonAnimation.state.SetAnimation(0, "anim1", false);
skeletonAnimation.state.Update(0);
skeletonAnimation.state.Apply(skeletonAnimation.skeleton);

This ensures that the animation state is updated and applied in the same frame, preventing any unwanted frames from appearing.

For more detailed information, you can refer to the Spine Unity documentation on setting animations.

    Spinebot skeletonAnimation.state.SetAnimation(0, "anim1", false);
    skeletonAnimation.state.Update(0);
    skeletonAnimation.state.Apply(skeletonAnimation.skeleton);

    Yes,this solves the problem,Thank you very much!

    Oh I tested it and the problem still exists - -

      c6u2 Another possible cause is that if anim1 or anim2 is a very short animation, but the mix duration is longer than the animation duration, it can go wrong. Could you please check if this applies to your case? If that doesn't solve the problem, please email the minimum Unity package that can reproduce the problem so we can see what the problem is: contact@esotericsoftware.com

      skeletonAnimation.state.SetAnimation(0, "idle", true);
      skeletonAnimation.state.Update(0);
      skeletonAnimation.state.Apply(skeletonAnimation.skeleton);

      skeletonAnimation.state.SetAnimation(0, "move", true);
      skeletonAnimation.state.Update(0);
      skeletonAnimation.state.Apply(skeletonAnimation.skeleton);

      Is there any issue with LOOP as this is the order of my calls?
      PS:
      Because I suspect that I may have made some errors in the underlying code during my previous optimization. I just pulled an old version of the 4.0 SPINEUNITY SDK from GitHub, but the problem still exists, perhaps related to the SPINE file?

        Spinebot If you need to interrupt the subsequent animation and ensure the previous animation plays normally, you can use the ClearTrack() method to clear the track before setting the new animation:

        Before this leads anyone astray: Note that ClearTrack() will prevent any animation mixing from happening, so you would get a clear cut without any transition.

        c6u2 Because I suspect that I may have made some errors in the underlying code during my previous optimization. I just pulled an old version of the 4.0 SPINEUNITY SDK from GitHub, but the problem still exists, perhaps related to the SPINE file?

        I assume that by "old version of the 4.0 SPINEUNITY SDK" you mean that you pulled the latest version from the 4.0 branch. Why do you use Spine 4.0 and not 4.2 if you're starting a new project? It's highly recommended to use 4.2 instead.

        Any I assume that by "SPINE file" you mean the exported skeleton .skel.bytes or .json asset. No, these are very likely not the problem.

        Most likely your code logic which calls the methods that sets the respective animations is wrong.

        You also don't need to call AnimationState.Update(0); and AnimationState.Apply(skeleton) manually just for setting animations if you want transitions. It's just necessary e.g. when repacking skins where you want everything updated in the same frame (regardless of the update order of your script) and not a frame later.

        You can add some debug log statements near the SetAnimation calls to see when which animation is set, or add breakpoints at the respective lines.

        c6u2 Is there any issue with LOOP as this is the order of my calls?

        No, loop is not a problem.

        • c6u2 odgovara na ovo.

          Harald

          Because the early projects and structures used 4.0, there was no intention of upgrading consistently.
          I only have one place to call skeletonAnimation. state.SetAnimation function with three anim state"idel","move","attack",but I found out that "move" doesn't always play successfully,So I just want to be able to play successfully every time.

            Harald Additionally, I will dynamically change SkeletonAnimation. Skeleton FlipX, I don't know if there's a problem with this?

              c6u2 Additionally, I will dynamically change SkeletonAnimation. Skeleton FlipX, I don't know if there's a problem with this?

              No.

              c6u2 I only have one place to call skeletonAnimation. state.SetAnimation function with three anim state"idel","move","attack",but I found out that "move" doesn't always play successfully

              What is your "one place" where you are calling this from? What is the code logic involved with the call?
              Usually 99% of such issues are due to the wrong game logic triggering things in an undesired way.

              Did you add some debug print output to verify that your calls are issued as intended?

              • c6u2 odgovara na ovo.

                Harald
                I will call the playanim method in different places, and playanim is just calling skeletonAnimation state.SetAnimation.
                I tried to print the debugging information, and the most suspicious thing currently is that both attach and move were called at the same time in the same second, although it appears to be the same second in the console, I don't think it's possible to enter the function body at the same time.

                  c6u2 I tried to print the debugging information, and the most suspicious thing currently is that both attach and move were called at the same time in the same second, although it appears to be the same second in the console,

                  "same second" is much too vague. Add a Time.FrameCount to your debug output for example. You need to know exactly in which order things are called and what is called in the same frame. If your order of calls is:

                  frame 0: SetAnimation(0, idle, ..)
                  frame 20: SetAnimation(0, attack, ..)
                  frame 20: SetAnimation(0, idle, ..)

                  Then the call setting attack in frame 20 is not having any effect, since it's immediately replaced with idle in the same frame. Attack will then never play.

                  c6u2 although it appears to be the same second in the console, I don't think it's possible to enter the function body at the same time.

                  If you call the method from multiple threads, then yes. On a single thread things are of course happening sequentially 🙂. It seems that you're having troubles with fundamentals of using Unity, programming and debugging in general. Please note that adding a layer of complexity on top by using Spine is likely making things more difficult and frustrating. It might be a more rewarding approach to first create a working prototype moving just a cube around via user input, and then adding more complex things like animation on top once things work as desired.

                  • c6u2 odgovara na ovo.

                    Harald
                    Oh I debug like this. But the red box represents the animation that did not play properly.
                    I didn't use multithreading, I just called from different places.

                      c6u2 Oh I debug like this. But the red box represents the animation that did not play properly.

                      You cut the log window right where it would become interesting. As I said previously, if SetAnimation() is called twice in the same frame (for the same track index), the first animation which was never started will then never be played:

                      frame 0: SetAnimation(0, idle, ..)
                      frame 20: SetAnimation(0, attack, ..)
                      frame 20: SetAnimation(0, idle, ..)

                      You can also read this in the documentation of AnimationState.SetAnimation

                      "Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from)."

                      c6u2 I didn't use multithreading, I just called from different places.

                      I would be surprise if you did 😃.

                      • c6u2 odgovara na ovo.

                        Harald Sorry Harald,Sorry for taking up a lot of your time.I finally identified the problem as calling setemptyanim in an inconspicuous place- -.

                        @c6u2 Very glad to hear you've figured it out, thanks for letting us know!