• Editor
  • How does Mixing work

Related Discussions
...

Wanted to get a better idea of how mixing works. The documentation on the runtimes page says mixing will override the current pose by a % based on the alpha value you provide the Mix function. If you provide 0.75, then the bones will be 75% towards the new mixed animation.

I have found that if I don't change the mixing value though and just leave it at 0.2, it will eventually have the bones in the mixing animation at 100%.

Just want to make sure I'm using the function properly. Should I be increasing the alpha over time? Should I leave it as constant?

Assuming you're still using Unity:

AnimationState handles the crossfade mixing for you. You just need to set the crossfade durations in the Spine SkeletonData asset file. No need to touch the Animation class's Mix and Apply methods.

If you click on the SkeletonData asset file in the project folder panel, the options should show up in the Inspector panel. "Add Mix" actually means, "I want to add a specific crossfade duration between a pair of animations." AnimationState automatically detects when you're transitioning between the animations in that list.

For all other purposes, yes, mixing does exactly what you described.
At a low level— meaning you probably don't need to/shouldn't touch this stuff unless you're programming lower-level classes and functionality—, it works in conjunction with Animation.Apply. Animation.Apply applies a frame of animation at a specific point in the animation's timeline. Animation.Mix does the same thing but with with an "alpha" for a percentage towards that animation instead of fully applying it. These are called every Update so the alpha would change over time if you want crossfade code.

But, again, unless it's super customized crossfade logic, you don't need to do stuff like this; just let AnimationState do its thing.

Yep, still using Unity. I'll go through my code and start switching to using AnimationState and adding mix values between them.

I was originally using a runtime class tk2dSpineAnimation which contained an AnimationState within to handle the switching of animations. All you had to do was supply the tk2dSpineAnimation class with the string of the animation you're switching to and it would do the rest. The implementation did not seem complete at that point and did not provide me with the control I needed over the animations so I ended up abandoning it and using the Mix/Apply functions.

Currently I'm also using the Apply function to play an animation backwards. Is this possible with AnimationState?

The change-the-string-to-play-an-animation interface was old and was fixed in May— Nate said he didn't like the string thing anyway. The queue system was added too. And you can now call AnimationState's SetAnimation and AddAnimation methods reliably to change the animation and queue them up.

I'm actually looking ask Nate if non-overriding play methods could be added to AnimationState, once he gets back. Right now, I have a bunch of wrapper classes to make up for what SkeletonAnimation can't do yet by itself, but I'm just doing a bunch of standard stuff.

I've tried playing animations backwards with AnimationState by setting the timeScale of the SpineAnimation component to a negative number. It didn't work (despite what Nate said). Someone was asking the same thing a few months ago. Not sure if it was you.

If you were making some specialized stuff anyway, you should just take a look at AnimationState and copy what it does. Apart from the reverse playing, it handles things pretty well. Or you could extend it maybe?

7 dana kasnije
Pharan wrote

I've tried playing animations backwards with AnimationState by setting the timeScale of the SpineAnimation component to a negative number. It didn't work (despite what Nate said).

Ah, right. AnimationState expects the times to increment, eg for queuing and mixing. I played with accepting a negative delta but it wasn't clean. The best I came up with was a separate method (or boolean checks in apply) like this:

	public void applyBackward (Skeleton skeleton) {
		if (current == null) return;
		if (previous != null) {
			previous.apply(skeleton, previous.getDuration() - (previousTime % previous.getDuration()), previousLoop);

		float alpha = mixTime / mixDuration;
		if (alpha >= 1) {
			alpha = 1;
			previous = null;
		}
		current.mix(skeleton, current.getDuration() - (currentTime % current.getDuration()), currentLoop, alpha);
	} else
		current.apply(skeleton, current.getDuration() - (currentTime % current.getDuration()), currentLoop);
}

The only issue with this is that you can't switch smoothly from backward to forward. If you stop calling apply and begin calling applyBackward, there will be a jump in your animation because the times will be interpreted differently. This is not the same as calling with a positive delta and then a negative delta (if negative delta were supported).

So, I don't think there is a clean solution to playing animations backwards using AnimationState, sorry!