• Modifié

Hi there,
Recently, within the last few months (updates) I've been getting bug reports from the dev team working in unity that animations are showing up in strange ways. For example, I have the scale, image and slot keys turned off(or 0 opacity in the case of the slot) at the first frame of the animation then the image scales up further down the timeline. This is how it's supposed to animate. What the developers are seeing in unity is the image on the first frame flashing at full scale then starting as intended. These are simple keying actions in the timeline, why is it coming out all strange in the unity side of things all of a sudden. I need to find convoluted ways around what used to be the simplest things you could possibly do in Spine. Thoughts?

    Related Discussions
    ...

    Usually it's better to hide the attachment, not just set opacity to zero. It won't cause the problems you describe, but drawing an attachment image with 0 opacity will still draw pixels and count against your pixel fill rate, unless the renderer has a special case.

    What you describe, the wrong pose for 1 frame, likely comes from setting an animation at the wrong time during the Unity frame lifecycle. If an animation is set after animations are applied, then the new animation won't be applied until next frame. This results in whatever the skeleton pose used to be showing for 1 frame. It may not be noticeable in some cases, if the pose happens to be similar to the pose from the new animation, like when changing from one animation to another. However, if the old pose is sufficiently different, such as the setup pose rather than a pose from an animation that you will mix from, then it can be noticeable.

    There is not a fix for this in the Spine editor. Your programmers will need to be wary of when they change animations within the frame lifecycle. Ideally they do it before animations are applied. If not, they can apply animations after they set new animations.

    If the first frame of an animation is playing back incorrectly with a sudden "jump" thereafter, it sounds as if your programmers are setting animations at the wrong time in the Unity update cycle, or are otherwise modifying the skeleton incorrectly.

    How are your animators setting and switching between animations?
    Do your animators see the correct animation played back in the SkeletonDataAsset Inspector Preview window when playing back each animation?

    One you could also check is to make sure Animation Cleanup is disabled when exporting your skeleton. Otherwise keys identical to the setup pose are removed, which may cause problems when layering animations. This is likely not the problem, but just mentioning to be sure.

    In general we would be happy to talk directly to your programmers. If they can send us a minimal Unity project which demonstrates their issue, we will be able to help most quickly. They can send us the minimal project as a zip package to contact@esotericsoftware.com, briefly mentioning this forum thread URL so that we know the context.

    lui (or 0 opacity in the case of the slot)

    Please note that setting the opacity to 0 will still render any attachment, just at full transparency (with vertex color alpha set to 0). If you don't want the slot's attachment to be included in the mesh (rendered at all), you should key the attachment as disabled.

    Since admittedly rarely anyone is using vertex color alpha in another way than transparency in a custom shader, we will likely exclude alpha=0 attachments from the mesh in future spine-unity versions.

    Just noticed after posting that Nate already replied, sorry for the duplicate information. 🙂

    Hey, dev here.

    The animation in question was being started after the .Complete callback was fired from a previous idle animation. I was using the AnimationState.SetAnimation method to do so both in that callback and for the original animation.

    I just tried using the AddAnimation method to see if queueing it up that way would avoid the problem, and it improved it quite a bit, though it isn't perfect.

    Is there somewhere I can learn more about setting animations in the appropriate time in the Unity update cycle? I assumed queueing them up using the AddAnimation would be an appropriate method.

      @arcbox Thanks for getting in touch, this will for sure speed things up.

      arcbox The animation in question was being started after the .Complete callback was fired from a previous idle animation.

      This is unfortunately a quite ambiguous description. By "was being started after the .Complete callback", do you mean you called SetAnimation (or AddAnimation) from your callback method which is hooked up to the .Complete callback? Or did you set e.g. a bool property and then in the next Update call of your component check this bool parameter and call SetAnimation?

      Please where possible share source code, prose text is always prone to being ambiguous or even wrong.

      Also please describe in a bit more detail what your transition setup currently looks like, what you want to achive. E.g. "You receive user input or whatever event at any time to start a move-right animation and want to exit an idle animation loop when it's at the end of the animation. There should be mix transition from the idle to the move-right animation of (mixDuration) 0.2 second (or alternatively, no transition at all), starting at 0.2 seconds before the end of idle.

      Also note that if you have set a non-looping idle animation and call SetAnimation from the .Complete callback (being at the last frame), you have no animated frames left for the 0.2 second mix transition where idle mixes into move-right. If you don't want any mix transition between idle and walk-right to happen, that's ok, then you usually either set your Default Mix Duration at the SkeletonDataAsset to 0.0 seconds, or at individual animations set trackEntry.mixDuration = 0.0f (at the newly added or set animation, not at the preceding one).

      arcbox I just tried using the AddAnimation method to see if queueing it up that way would avoid the problem, and it improved it quite a bit, though it isn't perfect.

      Please always describe what you expected to see and what you see instead. We're sorry to hear that it "isn't perfect", but given this description we are left with guessing what could be your problem. As a programmer you would also not like to get an issue report that just says "isn't perfect". 🙂

      Do you see the last frame of your previous animation too long, are you missing a transition, are you seeing a completely uncorrelated pose for one frame which is neither from the previous nor from the next animation?

      It would likely be easiest if you could share a minimal Unity project which shows your problem and send it as a zip package to contact@esotericsoftware.com, and briefly mentioning this forum thread URL so that we know the context. Then we can have a look at whether the animation itself is causing the problems or whether your code is doing something wrong.

      arcbox Is there somewhere I can learn more about setting animations in the appropriate time in the Unity update cycle? I assumed queueing them up using the AddAnimation would be an appropriate method.

      The following documentation sections are most relevant for animation updates and callbacks:
      https://esotericsoftware.com/spine-unity#Life-cycle
      https://esotericsoftware.com/spine-unity#Processing-AnimationState-Events
      Also, the Spine API documentation is always the go-to reference for how exactly any parameters or method calls affect the skeleton:
      http://esotericsoftware.com/spine-api-reference#TrackEntry-mixDuration

      Nevertheless, it's usually not that complicated to set an animation and let a mix of the desired duration (or none at all) happen when one animation transitions to another 🙂. It would likely be easiest if we have a look at your minimal reproduction project, perhaps your animation code is not the problem.

      Sorry about being vague, I guess from my perspective I'm using such a small portion of the API that it seems very simple but you don't have the same context so that wasn't very helpful of me.

      I start off by setting an idle animation for the character, using the AnimationState.SetAnimation method:
      skeletonAnimation.state.SetAnimation(0, "idle" true);

      Then, at some point that is triggered by the player we replace that idle with a one-time animation, and return back to the idle animation afterward. The animations have been close enough that we haven't needed to do any mixing:
      skeletonAnimation.state.SetAnimation(0, "action", false);
      skeletonAnimation.state.AddAnimation(0, "idle", true, 0);

      What is happening is that when the first idle switches to the action animation it is showing one frame of a sprite turned on at full scale when the artist has done everything to ensure that sprite is hidden in the first frame of the action animation. The sprite immediately tweens down to the scale and opacity the artist has set, rather than being that way from the beginning.

      Here is the example, you can see the question marks are immediately visible, and then tween down. They are supposed to start at no scale and tween up based on how the animation is setup in Spine.

      Thank you for your time, and let me know if I can provide any additional detail.

        arcbox The animations have been close enough that we haven't needed to do any mixing:

        I assume that there is some misunderstanding. You always get mixing between animations of length Default Mix Duration set in the SkeletonDataAsset. If you did not change that value to 0.0, you receive a default of 0.2 seconds of mix transition between animations. You can either modify this value in the SkeletonDataAsset or at each TrackEntry that you receive from SetAnimation or AddAnimation calls.

        arcbox What is happening is that when the first idle switches to the action animation it is showing one frame of a sprite turned on at full scale when the artist has done everything to ensure that sprite is hidden in the first frame of the action animation. The sprite immediately tweens down to the scale and opacity the artist has set, rather than being that way from the beginning.

        If you left the default mix duration at 0.2 seconds as-is, this would explain the behaviour. You have the previous idle animation using the undesired large scale value, and when transitioning over 0.2 seconds to the new animation the scale linearly interpolated from large scale to desired scale.

        Note that any float values will transition linearly between old animation to new animation over MixDuration, including alpha opacity values. When one animation set them to 1.0 and the new animation sets them to 0.0, you receive a linear transition from 1.0 to 0.0 over newAnimationTrackEntry.MixDuration seconds.

        Visibility of attachments however is a binary value with no in-between values, here trackEntry.AttachmentThreshold the mix threshold when the new animation's value is used. If you want immediate visibility change of attachments (visible to hidden), but at the same time want smooth mix transitions at e.g. bone rotation, your animator could key Attachment visibility instead of setting alpha opacity values.

        @arcbox You can also specify MixDuration for each pair of animations in the SkeletonDataAsset Inspector as described here:
        https://esotericsoftware.com/spine-unity#Mix-Settings
        And you can set default values for Default Mix Duration at each newly imported skeleton assets in the Spine Preferences, to save you from having to set it to 0.0 for each skeleton:
        https://esotericsoftware.com/spine-unity#Spine-Preferences

        @arcbox And thanks for providing the detailed description above, it helped a lot! I missed to mention that before since I was so glad to be able to provide a more helpful description of what is likely going wrong. 🙂

        Thanks for taking the time to offer your advice, much appreciated!