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?
Page 1 of 1
dev27
2.5 years ago
- dev27
- Posts: 6
Harald
You should not need to go as low-level as dealing with individual
You can apply a single Animation as the code on the reference page shows:
spine-runtimes/SkeletonMecanim.cs at 3.8
You can have a look at the
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. 2.5 years ago
-
Harald - Posts: 4107
dev27
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// 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);
}
2.5 years ago
- dev27
- Posts: 6
Harald
You do not want to mix your animation with
So you should be able to receive blended animation with the following code:
MixBlend.Setup
, this will use the setup pose instead of your animation that you wish to transition to.Unless I misunderstood your statement, this is not correct - alldev27 wrote:Alpha affects mixing progress directly only by MixBlend.Setup to mix from setup state
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. 2.5 years ago
-
Harald - Posts: 4107
dev27
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.{
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);
}
}
}
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
2.5 years ago
- dev27
- Posts: 6
Harald
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
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);
}
}
}
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);
}
}
}
2.5 years ago
-
Harald - Posts: 4107
dev27
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
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

2.5 years ago
- dev27
- Posts: 6
Harald
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! 
2.5 years ago
-
Harald - Posts: 4107
Mark topic unread
• Page 1 of 1
Return to Unity
- All times are UTC