- 已编辑
Unexpected behavior with AddEmptyAnimation
Code snippet - this is performed on a SkeletonAnimation that has no other animations playing or anything else going on with it:
if (Input.GetKeyDown(KeyCode.I)) {
skeletonAnimation.AnimationState.AddAnimation(0, "animation_name", false, 0);
skeletonAnimation.AnimationState.AddEmptyAnimation(0, 0, 0);
}
What I expect to happen: I press the "i" key, and it plays the full 1 second long "animation_name" animation, and when it finishes the empty animation clears the track.
What I actually happens: I press the "i" key, and it plays the "animation_name" animation for a single frame, and then switches to the empty animation and gets cleared. If the "mixDuration" on the empty animation is set to 0 then the Track goes back to "null" after 2 frames (one frame of "animation_name" and one frame of "<empty>")
Am I misunderstanding how AddEmptyAnimation is supposed to work? I assumed it would queue the empty animation after the "animation_name".
Notes:
-I'm using the latest version of Spine 3.8
The behavior I see with spine-libgdx is what you expect: the animation plays, afterward the empty animation resets to the setup pose. My code was with spineboy and:
state.addAnimation(0, "walk", true, 0);
state.addEmptyAnimation(0, 0, 0);
Harald will take a look at spine-unity ASAP.
Nate :The behavior I see with spine-libgdx is what you expect: the animation plays, afterward the empty animation resets to the setup pose. My code was with spineboy and:
state.addAnimation(0, "walk", true, 0); state.addEmptyAnimation(0, 0, 0);
Harald will take a look at spine-unity ASAP.
Thanks Nate - if everything seems fine on the spine-unity side I'd be glad to set up a repro
Thanks, no need for a repro. We found out that it's actually a problematic case (in other runtimes as well) where DefaultMixDuration
is used to shorten the delay. Even when a successive entry.MixDuration = 0;
call makes any transition immediate, the delay has been shortened already. If DefaultMixDuration
is only 0.1s
it's barely noticable that the animation ends a bit early, but when DefaultMixDuration
is e.g. 0.5s
or longer it's getting very noticable.
We are currently working on a fix, we'll let you know once it's ready. Thanks for reporting!
You can see the problematic code here:
spine-runtimes/AnimationState.java at 3.8
AnimationState addAnimation
sets the TrackEntry delay
as described there, using the default mix duration, then the TrackEntry mixDuration
is set to what was passed to addEmptyAnimation
. This leaves the delay based on the previous animation's duration and default mix duration, not the mix duration specified to addEmptyAnimation
.
We've fixed this in 4.0-beta. Unfortunately it's a little too risky to apply the changes to 3.8. You could work around it in in 3.8 by not using a default mix, or by porting the changes, or by setting the delay yourself after calling addEmptyAnimation
. That could look like (untested):
prev = skeletonAnimation.AnimationState.AddAnimation(0, "animation_name", false, 0);
empty = skeletonAnimation.AnimationState.AddEmptyAnimation(0, 0, 0);
empty.Delay = prev.AnimationEnd - empty.MixDuration;
Since your mix duration is 0 you only really need empty.Delay = prev.AnimationEnd;
. It's more difficult when you don't have a reference to the entry before the empty one (then you need getCurrent
and access next
until you reach the end of the list, before you add the empty animation).
Fix commit in 4.0-beta
:
https://github.com/EsotericSoftware/spine-runtimes/commit/fbd18ec0cbecae19e11ae6bc7f0be501fd16d45f
Usage is described in beta API reference:
API Reference (beta) - Spine Runtimes Guide: TrackEntry mixDuration
Thanks for the fast response guys! That workaround should be good - I do indeed have a reference to "prev" so should be a cinch. :yes:
(and yeah, I am using a large DefaultMix of 1.0f for that character hah)
Glad to hear that it was based on the same problem, thanks for letting us know!
When using the 3.8 branch, the workaround for now is setting default mix duration to the desired value and later resetting it:
var savedDefaultMix = skeletonAnimation.AnimationState.Data.DefaultMix;
skeletonAnimation.AnimationState.Data.DefaultMix = 0.0f;
skeletonAnimation.AnimationState.AddEmptyAnimation(0, 0, 0);
skeletonAnimation.AnimationState.Data.DefaultMix = savedDefaultMix;
This leads to the proper delay being used.