• Editor
  • Something like "blend trees"?

Hello everyone,

I would like to know if it's possible to recreate the behavior of a Unity Animator's blend tree using the Spine runtime editor in Unity. Currently, I have a blend tree with two variables, representing horizontal and vertical inputs, and four animations for character movement (left, right, up, and down). My goal is to have animations overlap or blend based on the input values, creating a smooth transition for diagonal movement by visualizing an "intermediate" animation between the two primary directions.

Is this achievable?

I've attached an image illustrating what I mean in Unity's blend tree.

Thank you everyone in advance!

Related Discussions
...

Yes, you can do this using the AnimationState API and MixBlend.add. Make sure you reset the properties keyed in additively applied animations each frame, before applying the additive animations.

There's demo code here:
EsotericSoftware/spine-runtimesblob/4.1/spine-ts/spine-webgl/demos/additiveblending.js
Can see it live here:
http://esotericsoftware.com/spine-demos#Additive-blending

Additive animations allow you to do weighted animation blending. You can combine any number of animations by setting their TrackEntry alpha so that they all sum to 1. You can use it for directions or anything else. For example, you could have happy, sad, angry, laughing, etc animations and mix them all like 10% happy, 20% sad, 30% angry, 40% laughing (summing to 100%, though it's not required).

    Thank you for your answer, @Nate.

    I'll let my programmer research all this information, I think I understand the idea but I have no clue of how to implement it haha.

    I'll let you know if this solves the issue. Thank you!

    5 days later

    Nate Hi! First of all, Happy New Year!

    Your response helped solve the problem! After a bit of research, I managed to adapt it to my project and understood it well enough for everything to work, except for one small thing.

    Right now, the code that interpolates between animations can be summarized in this code:

    left.Alpha = (horizontalInput < 0) ? -horizontalInput : 0;
    right.Alpha = (horizontalInput > 0) ? horizontalInput : 0;
    up.Alpha = (verticalInput > 0) ? verticalInput : 0;
    down.Alpha = (verticalInput < 0) ? -verticalInput : 0;
    skeleton.SetBonesToSetupPose();

    However, when transitioning from "right" to "left," the change is very abrupt, and there is no interpolation there. Can you think of any way to smooth the transition from one animation to the "opposite"? I would greatly appreciate any help in this regard.

    Thanks in advance!

      Yimec Happy New Year! 🌟

      Can you think of any way to smooth the transition from one animation to the "opposite"?

      You can create transition animations for it.
      Spineboy has a transition animation for changing direction: idle-turn. It may be difficult to see what Spineboy is doing because he does not actually turn in the animation, so to make it easier to see how it is actually used, I have attached a video of an example scene Spine Examples/Getting Started/2 Controlling Animation:

      The idle-turn animation is simply played before the idle animation is played; Spineboy's orientation change occurs at the same time the idle-turn animation starts playing. See the actual scene for more information.

      Thanks for your help, @Misaki !

      I've been checking the scene, but I have no clue of how to include this new animation in my script or how to key it in my particular scenario. Could you give some directions? If needed, I could provide you with the complete script.

      Thank you in advance!

        What is the value of eg horizontalInput? If it is 1 or -1 then it would be abrupt. It sounds like what you want is for it to transitions from 0 to 1 over time.

        Yimec The transition animation is set by a script named SpineBeginnerTwo.cs, so you may want to check that first. In this script, when flipping the skeleton, the transition animation is set first with setAnimation() and the post-transition animation is added to the same track with addAnimation(). The relevant lines are here.

        Just to be clear, what I am suggesting is not using animation blending, but simply preparing an animation to play when the skeleton is flipped. However, I believe this is a common way to smoothly change the direction of the character.

        Thank you very much for the responses!

        @Nate
        The value of horizontalInputis equivalent to the joystick, ranging from 0 to 1, passing through all intermediate values. There's not a big issue there. The problem arises when playing with the keyboard since there's no "lever" to gradate the value, and the transition from 0 to 1 is sudden.

        @Misaki
        I've looked at the script you mentioned, and it's easy to understand what it does. However, I find it not so straightforward to figure out how to use the same method (with AddAnimation) while combining it with animation blending.

        A good example I've found, and I would swear it's done with Spine, is The Knight Witch and its main character animations. I'm attaching a video showing how the transition from one animation to the opposite is smoothed.

        Thank you very much for your help, and I hope we can find the solution. Thanks in advance!

          Yimec Hmmm, the flipping shown in the video you attached looks like the same way Spineboy does the transition animation playback. Could you actually show us what you tried and how it looks like? If you do not want to post it in the forum, you can email us a video that shows the problem: contact@esotericsoftware.com

          @Misaki I just sent an email with a video showing the issue. I hope it helps!

          Thank you!!

            Yimec Thanks for sending a video! Is it the backwards movement with the skeleton facing the same direction that you want to achieve? When you say that the change from right to left is abrupt, do you mean that the rotation of the arms does not change smoothly? Can you show us the code how the current right-to-left transition is implemented?

            Exactly, is the arms abrupt change what I want to avoid. In the reference video you can see how the leg is reoriented smoothly.

            The code is pretty simple and I attached it in previous posts, but here you got the complete script (at least, what is related to the animation mixing):

            using System.Collections;
            using System.Collections.Generic;
            using UnityEngine;
            using Spine.Unity;
            using Spine;
            
            public class PlayerAnimationBehaviour : MonoBehaviour
            {
            
                [Header("General Animations")]
                [SerializeField] [SpineAnimation] private string idleAnimation;
                [SerializeField] [SpineAnimation] private string idleFace;
                [SerializeField] [SpineAnimation] private string upAnimation;
                [SerializeField] [SpineAnimation] private string downAnimation;
                [SerializeField] [SpineAnimation] private string leftAnimation;
                [SerializeField] [SpineAnimation] private string rightAnimation;
            
                [SerializeField] private SkeletonAnimation skeletonAnimation;
                public Spine.AnimationState spineAnimationState;
                public Spine.Skeleton skeleton;
            
                private TrackEntry up, down, left, right;
            
                [Range(-1.0f, 1f)]
                public float horizontal = 0f;
                [Range(-1f, 1f)]
                public float vertical = 0f;
            
                [SerializeField] private bool isMovable = true;
            void Awake()
                {
                    spineAnimationState = skeletonAnimation.AnimationState;
                    skeleton = skeletonAnimation.Skeleton;
            
                    spineAnimationState.SetAnimation(0, idleAnimation, true);
                    spineAnimationState.SetAnimation(1, idleFace, true);
            
                    left = spineAnimationState.SetAnimation(2, leftAnimation, true);
                    right = spineAnimationState.SetAnimation(3, rightAnimation, true);
                    up = spineAnimationState.SetAnimation(4, upAnimation, true);
                    down = spineAnimationState.SetAnimation(5, downAnimation, true);
            
                    left.MixBlend = MixBlend.Add;
                    right.MixBlend = MixBlend.Add;
                    up.MixBlend = MixBlend.Add;
                    down.MixBlend = MixBlend.Add;
            
                    left.Alpha = 0;
                    right.Alpha = 0;
                    up.Alpha = 0;
                    down.Alpha = 0;
            
                }
            
            void Update()
                {
                    if (isMovable)
                    {
                        BlendAnimations(moveInputs.x, moveInputs.y);
                    }
            
                }
            
             private void BlendAnimations(float horizontalInput, float verticalInput)
                {
                    
                    left.Alpha = (horizontalInput < 0) ? -horizontalInput : 0;
                    right.Alpha = (horizontalInput > 0) ? horizontalInput : 0;
                    up.Alpha = (verticalInput > 0) ? verticalInput : 0;
                    down.Alpha = (verticalInput < 0) ? -verticalInput : 0;
                    
                   
                    skeleton.SetBonesToSetupPose();
                }

            Let me know if this helps you clarify the issue or if I should approach this problem any other way.

            Thank you!

            Edit: moveInputs.x and moveInputs.y is provided by the RewiredManager, I did not include that part in the copied code.

              If the problem is the keyboard flips from 1 to -1 without intermediary values, then you could make it have intermediary values. For example, use 1 or -1 in your game code, but when changing from 1 to -1 or vice versa, write code that does it over a short period of time, solely for the animation. You could even base this time on how fast the character is moving. A slow character turns more quickly than one moving fast, eg Super Mario.

              Yimec Thanks for showing us the code. It looks like Nate's advice is correct after all. It seems to me that all you need to do to achieve what you want is to be able to gradually raise the alpha from 0 to 1.

              However, I am a little concerned about whether or not it is necessary to separate tracks in the first place for movements in opposite directions, such as leftAnimation and rightAnimation. I tried blending two types of Spineboy walk animations, one for a forward walk and one for a backward walk, but the animation blending results are a bit weird, especially when the alpha is low. The video below shows what I tried in the preview view in Spine:

              Even when using Mix, the animation transition can end up being a little less smooth, depending on the timing of the animation, but I think this can be fixed by adding a short transition animation between them.

              Hello everyone!

              I've been testing with my code and I think we've achieved a solution!

              @Nate gave me the solution, I just replace the "input" value itself with a value that gradually changes, and now it feels right. For now, this solution is more than enough, so we will stick to it.

              Thank you both for your help and advice, I really feel supported every time I post in this forum!