• Unity
  • How to control mixing between animations?

Related Discussions
...

Hi guys,

I want to mix from current animation frame to the first frame of other animation. My problem is that I want to ease this process with some easing function, so I think I have to adjust the alpha property over time. As I understand, I have to implement this
http://de.esotericsoftware.com/spine-applying-animations#Timeline-API but i have no idea how, can you give me some example with this lowest level API?

You should not need to go as low-level as dealing with individual Timelines, it should be sufficient to handle the transition on the Animation level.

You can apply a single Animation as the code on the reference page shows:

animation.apply(skeleton, lastTime, time, loop, events, alpha, blend, direction);

You could also have a look at the SkeletonMecanim component, it blends single animations manually without using SkeletonRenderer's AnimationState:
spine-runtimes/SkeletonMecanim.cs at 3.8

You can have a look at the SpineGauge example scene that is included in the spine-unity package. It uses a SkeletonRenderer and directly applies an animation. Note that it's just a single animation (using MixBlend.Setup) instead of a transition-overlay, and in the example it increases the time value instead of the alpha value (alpha is constantly set to 1.0), but I assume you get the clue.

public AnimationReferenceAsset SomeAnimation; //choose animation asset to which you want make transition in inspector
// reference assets can be generated from your skeleton data with the press of a button in your SkeletonDataAsset's inspector

float easedTime; // from 0 to 1
//.... ease it with some Ease function

void Update()
{
      SomeAnimation.Animation.Apply(skeleton, 0, 0, false, null, easedTime, MixBlend.Setup, MixDirection.In);
}

Alpha affects mixing progress directly only by MixBlend.Setup to mix from setup state, but i couldn't find a way how to control mixing from current animation state to other animation by MixBlend.Replace or MixBlend.First

You do not want to mix your animation with MixBlend.Setup, this will use the setup pose instead of your animation that you wish to transition to.

dev27 a écrit

Alpha affects mixing progress directly only by MixBlend.Setup to mix from setup state

Unless I misunderstood your statement, this is not correct - all Timelines respect the alpha parameter in Apply().
So you should be able to receive blended animation with the following code:

SomeAnimation.Animation.Apply(skeleton, 0, 0, false, null, easedTime, MixBlend.Replace, MixDirection.In);

Note however, that when using 0.0 as timepoint of the animation and you have not set any key at time 0 (nothing keyed at the start time), Apply() will not have any effect unless using modes MixBlend.Setup or MixBlend.First, maybe that is the problem you are facing.

public class AnimController : MonoBehaviour
{
   public AnimationReferenceAsset otherAnimation;

   SkeletonAnimation skeletonAnimation;
    Spine.Skeleton skeleton;
   Spine.AnimationState spineAnimationState;

   bool mixing = false;
   float easedTime;

void Start()
{
    skeletonAnimation = GetComponent<SkeletonAnimation>();
  skeleton = skeletonAnimation.Skeleton;
  spineAnimationState = skeletonAnimation.AnimationState;

  spineAnimationState.SetAnimation(0, "animation", true);

  Invoke("makeTransitionToOtherAnimation", 3);
   }

void makeTransitionToOtherAnimation()
   {
      spineAnimationState.ClearTracks();

  mixing = true;
  easedTime = 0.1f;
   }

void Update()
   {
      if (mixing)
      {
         otherAnimation.Animation.Apply(skeleton, 0, 0, false, null, easedTime, MixBlend.Replace, MixDirection.In);
      }
   }
}

Thats exactly why i need MixBlend.Replace, but it doesnt work like by MixBlend.Setup. If alpha parameter stays constant for example 0.1f (10 percent of transition between animations) animation is going to be blended to the end anyway. And of course i have key at time 0.
I've made an example project, so you can see how your runtime works by MixBlend.Replace, take a look https://mega.nz/#!zIMAxIDC!a-4pKgLfjfiyGIFYnMhkw8wkMtDFf00UdRunw_6duzE

The problem with your code was that it first clears the track, then there is no active track left as a solid base to add the alpha-blended new track to. So it adds 10% of your new animation to the previous frame state.

I have fixed your code, using the UpdateLocal callback method you can be sure that your code gets called after the other animations have been applied, so there is no need to call ClearTracks():

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using Spine.Unity;
using Spine;


public class AnimController : MonoBehaviour
{
   public AnimationReferenceAsset otherAnimation;



   SkeletonAnimation skeletonAnimation;
    Spine.Skeleton skeleton;
   Spine.AnimationState spineAnimationState;

   bool mixing = false;
   public float easedTime;

void Start()
{
    skeletonAnimation = GetComponent<SkeletonAnimation>();
  skeleton = skeletonAnimation.Skeleton;
  spineAnimationState = skeletonAnimation.AnimationState;

  spineAnimationState.SetAnimation(0, "animation", true);

  skeletonAnimation.UpdateLocal += OnUpdateLocal;

  Invoke("makeTransitionToOtherAnimation", 3);
   }

void makeTransitionToOtherAnimation()
   {
      //spineAnimationState.ClearTracks(); // no need to clear tracks, unless you really want to.
      mixing = true;
   }

   void OnUpdateLocal(ISkeletonAnimation animated)
   {
      if (mixing)
      {
         //skeleton.SetBonesToSetupPose(); // if you cleared the tracks, this line would be necessary to base any blending on the setup pose, otherwise you have the previous frame state as a base.
         otherAnimation.Animation.Apply(skeleton, 0, 1, false, null, easedTime, MixBlend.Replace, MixDirection.In);
      }
   }
}

I just want to stop current animation and make transition from current frame state to first keyframe of other animation.
Your code doesn't stop current animation.

//edited
i uncommented skeleton.SetBonesToSetupPose(); and it does the trick, but the bones that have no keyframes in otherAnimation are setted to Setup position and i have to handle it somehow.
It would be much better to have option to blend just from current frame state to other state without SetBonesToSetupPose()

// edited 2
your variant without stopping current animation is actually better, i just clear tracks after blending

Thank you for your help 🙂

Yes, I provided the commented-out code with some comments in case you wanted to stick to the ClearTracks() workflow. Anyway, I also think that not clearing the track would lead to nicer transitions in most cases. Glad you figured it out! 🙂