• RuntimesUnity
  • Non-linear Unity timeline traversal

Hey guys,
We've been using spine at work and been doing some unique things via Unity's timeline system and spine. However, I am currently running into some oddities that I can't seem to work out.

So I am currently trying to make non-linear timelines to loop parts of the spine animation by jumping to earlier (and eventually later) timestamps in the timeline via timeline markers/notifications. The peculiar thing I'm seeing is that in edit time I can scrub/play the playable director and watch the spine animation follow the playhead accurately as it hops back in time. However when I hit play and watch it in runtime, the spine animation plays once fully and ignores the playhead of the playable director as it loops.

When I dig into the source code of the mixer behavior, I see that there's a special code block dedicated to the preview mode when the application isn't running. Is the behavior just something I can't do anything about or is there some settings I can do to get the spine animation to follow the playable director's playhead in runtime as I hop around the timeline?

I am working with SkeletonAnimations and am using the following package versions:
Timeline extensions: 4.1.9
CSharp runtime: 4.1.0
Unity Runtime: 4.1.15
URP Shaders: 4.1.17

Also another issue I also ran into was that setting the boolean flag of Clip End Mix Out Duration on the SpineAnimationStateClip doesn't seem to blend the spine animation back to empty when it's the last clip on the timeline asset. Our idle animation is set up on spine track index 0 and the SpineAnimationStateTracks modify track indices 1 and beyond. As a workaround I have the code modifying the timeline assets to append a 1f empty SpineAnimationStateClip to the end of any timeline that has the last object be an SpineAnimationStateClip to empty out the spine track index.

    Related Discussions
    ...

    TheBiter boolean flag of Clip End Mix Out Duration on the SpineAnimationStateClip

    Which boolean flag do you mean? Clip End Mix Out Duration is a float parameter, and Don't End with Clip directly above disables the mix-out at clip end to the empty animation.

    TheBiter When I dig into the source code of the mixer behavior, I see that there's a special code block dedicated to the preview mode when the application isn't running. Is the behavior just something I can't do anything about or is there some settings I can do to get the spine animation to follow the playable director's playhead in runtime as I hop around the timeline?

    The preview-only code block which is only used outside of play mode on purpose, as it comes with some drawbacks and is not really reliable as soon as multiple tracks are used, or when the Timeline animation shall be combined with programmatic (non-Timeline) animation on other tracks.

    While you could always modify the source code accordingly if your project can cope with the drawbacks, we would not recommend that.

    If you could send us a minimal Unity project which demonstrates this issue of incorrect playback when you are jumping to fixed positions in the timeline, then we can have a look at what's going wrong and hopefully come up with a bugfix. You can send us your reproduction project as a zip package to contact@esotericsoftware.com, briefly mentioning this forum thread URL so that we know the context.

      Harald Which boolean flag do you mean? Clip End Mix Out Duration is a float parameter, and Don't End with Clip directly above disables the mix-out at clip end to the empty animation.

      Sorry I mistyped on the field type. Basically what I've observed is that when the spine clip is the very last thing on the timeline asset, Clip End Mix Out Duration doesn't seem to work regardless of how much duration I provide it. I want the spine animation that ran on spine track 1 to blend back to empty so that the idle animation on spine track 0 can play. Instead, the spine animation on track 1 seems to just hold and the spine rig never goes back to its idle animation and holds still.

      Harald If you could send us a minimal Unity project which demonstrates this issue of incorrect playback when you are jumping to fixed positions in the timeline, then we can have a look at what's going wrong and hopefully come up with a bugfix. You can send us your reproduction project as a zip package to [contact@esotericsoftware.com](mailto:contact@esotericsoftware.com), briefly mentioning this forum thread URL so that we know the context.

      I'll put one together by end of day today to send over. Thanks for being so responsive!

      @TheBiter Thanks for the additional info. Looking forward to the package. BTW: If you can reproduce the issue using the example skeletons that come with the spine-unity runtime (located in Spine Examples/Spine Skeletons), that would be great.

      @TheBiter Thanks for sending the reproduction project, we received everything and can reproduce the issue. We'll get back to you here on the forum as soon as we have a bugfix ready.

      @TheBiter We just pushed a bugfix for this issue to the 4.1 and 4.2-beta branches. New 4.1 and 4.2-beta Spine Timeline UPM packages are available for download here as usual:
      https://esotericsoftware.com/spine-unity-download
      Please let us know if this resolves the issues on your end as well. Thanks for reporting!

      Issue ticket URL for later reference:
      EsotericSoftware/spine-runtimes2316

        Harald

        I grabbed the newest UPM timeline package and it seems to work now. The spine animation follows the playhead as expected. This is wonderful! Thanks for being so quick on the uptake!

        I just want to mention the Clip End Mix Out Duration issue again where the last timeline clip on the spine animation track index doesn't blend back to empty. However, I have a workaround for this at the moment but it might be worth investigating.

        Again many thanks for being so quick on addressing the main issue!

          TheBiter

          I grabbed the newest UPM timeline package and it seems to work now. The spine animation follows the playhead as expected. This is wonderful! Thanks for being so quick on the uptake!

          Glad to hear it resolved your issue, thanks again for reporting!

          TheBiter I just want to mention the Clip End Mix Out Duration issue again where the last timeline clip on the spine animation track index doesn't blend back to empty. However, I have a workaround for this at the moment but it might be worth investigating.

          Oh, sorry, I forgot about this second issue! We will investigate the cause of the problem and get back to you as soon as we've figured out what's going wrong, or in case we fail to reproduce the issue.

          @TheBiter Unfortunately we indeed could not reproduce the issue with Clip End Mix Out Duration that you described above. Could you please send us another minimal Unity reproduction project? We found no such reproduction scene or TimelineAsset in your original reproduction package.

            Harald

            Maybe I'm not understanding the feature as it is designed. So what I thought Clip End Mix Out Duration does is to blend the animation on the spine track index defined in the timeline track back to empty when the clip is done playing.

            Example scenario I have a simple timeline asset of a single SpineAnimationStateTrack set to track index 1 and a single SpineAnimationStateClip with a jump animation reference asset assigned. Using the SkeletonAnimation Spineboy gameobject assigned to the playable director's track and idle set as its initial animation, I press play and expect to see the spineboy jump and then fully return to idle. Instead I see the Spineboy do his jump animation then get stuck in the last frame of his jump animation. He still moves his hip bone due to the jump animation not modifying it. So he's in the state where hes stuck in the last frame of the jump animation but his hip continues to move from the original idle animation, which I guess was playing throughout the duration of the jump but isn't noticeable.

            However if I then toss an empty signal emitter on the marker track past the last frame of the SpineAnimationStateClip, which extends the duration of the entire timeline asset past the last frame of the clip, I can see the Spineboy empty out his jump animation frames and return fully to idle. So this leads me to believe that in the case where the SpineAnimationStateClip is the last object on the timeline, it doesn't do Clip End Mix Out Duration properly.

            I did do a debug breakpoint step through of the code before to try to understand what was going on. What I think was happening is that in SpineAnimationStateMixerBehaviour script when the code hits the OnGraphStop method, isPaused is set to true in the scenario where the clip is the last thing on the timeline asset and thus never fires HandleClipEnd.

            I hope this is enough information to try to reproduce the issue I am seeing. Unless I misunderstood the feature entirely, it's something I am seeing on the most simple timeline setup. Thanks again for your time.

            @TheBiter Thanks for the detailed writeup. I just discovered that I overlooked that the test Timeline which I inspected had more animation clips following hidden to the right of the window (requiring scrolling), while I thought it had been the last clip already. My bad.

            We have created an issue ticket here for this issue:
            EsotericSoftware/spine-runtimes2318
            We will get back to you here on the forum as soon as we have a fix to offer.
            Thanks for reporting!

              Harald

              It's cool. I have a "good enough" workaround in the meantime to alleviate the behavior for our project.

              I also just noticed a different issue with the latest spine timeline package v4.1.10 that is hard for me to properly explain. It might be a result of the fix I requested for nonlinear traversal but when I have sequential clips in the timeline now (without any clip mixing overlap), the first clip's animation reference is ignored and the one located in the following 2nd clip is used instead. This only happens for the first SpineAnimationStateClip in the sequence as any following 2nd or 3rd or 4th clip seems to behave as normal.

              I'll be sending a sample reproduction project built upon my previous one with multiple playable directors and timeline assets in them to show off the behaviors in separate scenes. I've also bundled up the Clip End Mix Out Duration issue in there as well with the workarounds I've discovered in a separate scene.

              Thanks again for being so quick and responsive.

                TheBiter

                It's cool. I have a "good enough" workaround in the meantime to alleviate the behavior for our project.

                BTW: If you enable the clip option Don't pause with Director at your last clip, it will also mix out to the empty animation. Just in case that helps.

                TheBiter I'll be sending a sample reproduction project built upon my previous one with multiple playable directors and timeline assets in them to show off the behaviors in separate scenes.

                Sorry to hear you've encountered another problem. Thanks in advance for sending the reproduction project!

                  Harald BTW: If you enable the clip option Don't pause with Director at your last clip, it will also mix out to the empty animation. Just in case that helps.

                  AH! Yes, I'll keep that in mind. Thanks for the heads up.

                  Harald Sorry to hear you've encountered another problem. Thanks in advance for sending the reproduction project!

                  It's all good. I'm more concerned about other people grabbing the latest version and finding out they can't chain clips together.

                  Harald

                  Sorry for the delayed reply. So far in my tests with the new package and our non-linear timeline implementation, it all seems to be working great. I'm able to loop variable amount of times without issue and all the regular timelines are working fine as well. Thanks again for the fast turnaround!

                  I'll keep an eye out for the Clip End Mix Out Duration whenever you guys get that resolved. In the meantime our workaround is good enough. Many thanks!

                  @TheBiter Thanks for getting back to us, glad to hear everything worked out well!

                  We will post a reply here on the forum as soon as the Clip End Mix Out Duration bugfix update is ready.

                  @TheBiter We have just released an official bugfix for the Clip End Mix Out Duration issue. Timeline clips should now behave as the paramter names imply and follow the documentation again. Please let us know if this resolves the issue on your end as well. If you encounter anything else that behaves unexpectedly, please don't hesitate to let us know. Thanks again for reporting!

                  Updated 4.1 and 4.2-beta Spine Timeline UPM packages are available for download:
                  https://esotericsoftware.com/spine-unity-download

                    Harald

                    So in my testing reproduction project, I pulled down the latest package to test out the Clip End Mix Out Duration setting and it seems to work as expected now for the final clip, which is great.

                    I took a look at the logic that was changed and to me it looks a little confusing. Namely line 71 in SpineAnimationStateMixerBehaviour where it says bool isStoppedNotPaused = playable.GetGraph().IsPlaying(); // end of track was reached or graph stopped.

                    The observed behavior does seem to work as advertised but I just wanted to make sure this is the intended logic. From just reading the code one might assume the logic is reversed but with the way the timelines fire off the event timings, it's probably correct logic but just looks unintuitive.

                    Again thanks a bunch for the help! I believe all my issues have been resolved.

                      @TheBiter Thanks very much for the quick feedback, glad everything behaves as expected now!

                      TheBiter The observed behavior does seem to work as advertised but I just wanted to make sure this is the intended logic.

                      Thanks for taking a considerate look and sharing your concerns. The Unity Timeline API is unfortunately not always quite intuitive, as this example shows 🙂. Unfortunately OnBehaviourPause and OnGraphStop are both called in succession upon pausing or stopping the graph. The only way we found to distinguish whether these two successive calls are coming from a pause or stop event is that playable.GetGraph().IsPlaying() is returning false when paused and true when stopped.