• Unity
  • Briefly flashes previous animation state

Hello! Im updating an old game using Spine 3.7.91 in Unity before I submit it to ID@XBOX. We have an issue with 1 animation, and it just won’t play right. So, we have given up and hope someone here can help. Here’s the issue:

A rose is shown at different points in the game. The thorns grow a little longer each time & text is shown with it. When the 1st animation is played, it briefly flashes a different animation then plays. It happens so quick it can’t be screen recorded but is noticeable. I was able to record it on my cell phone, so I was able to look closely what was happening:

1st animation: briefly shows the final animation before starting
Every animation after that: briefly shows the previous animation before starting

Everything looks fine in spine. So, we were puzzled why it was doing it. In the end we almost got things to work. I added a second to the beginning/end of each animation and hid everything during that time. That way if it still showed the previous animation, its state would be hidden so in theory it wouldn’t matter if it flashed it. We just tested it and all the animations work except the 1st one. It still briefly flashes the final animation.

So, we don’t know what to do, so hopefully its something simple that was overlooked. Any ideas? The programmer that worked on the game originally is long gone, so I have a friend helping me that’s never used Spine before. It was supposed to be quick & only take about a day of work ha ha! Here’s the code my programmer is using in Unity. If you need more info let me know & I’ll have him check out the post.

_roseAnimation.SkeletonAnimation.gameObject.SetActive(true); var roseAnimation = _roseAnimation.SkeletonAnimation.GetComponent<SkeletonAnimation>(); roseAnimation.AnimationName = _roseAnimation.AnimationName; roseAnimation.AnimationState.Complete += (t) => _anim.Play("GameManagerFadeMusicOut");

Related Discussions
...
8 Bit Pxl wrote

_roseAnimation.SkeletonAnimation.gameObject.SetActive(true); var roseAnimation = _roseAnimation.SkeletonAnimation.GetComponent<SkeletonAnimation>(); roseAnimation.AnimationName = _roseAnimation.AnimationName; roseAnimation.AnimationState.Complete += (t) => _anim.Play("GameManagerFadeMusicOut");

I hope that the code does not all look like this and at least comes with proper indentation and line breaks. 🙂 Properly formatted it looks like this:

_roseAnimation.SkeletonAnimation.gameObject.SetActive(true);
var roseAnimation = _roseAnimation.SkeletonAnimation.GetComponent<SkeletonAnimation>();
roseAnimation.AnimationName = _roseAnimation.AnimationName;
roseAnimation.AnimationState.Complete += (t) => anim.Play("GameManagerFadeMusicOut");

The code posted above does not show anything problematic per se. I'm afraid we need additional context such as from where this animation is called, what is triggering this call, etc.

Harald wrote
8 Bit Pxl wrote

The code posted above does not show anything problematic per se. I'm afraid we need additional context such as from where this animation is called, what is triggering this call, etc.

I'll ask him for more info and have him post in here. Since I'm an artist and not a programmer, I have no idea what proper code format looks like. I just copy/pasted from a DM. He could have sent me a pic of a potato and told me it was code and I would have posted that, too ha ha. Luckily you knew what was intended.

No problem. 🙂

I'm the dev helping out on this project.

This animation plays on the completion event of a previous animation.

The method below is added to the previous animation's (_lastAnimation) complete event.

private void AnimationState_Complete(Spine.TrackEntry trackEntry)
{
    if (_roseAnimation != null && _roseAnimation.SkeletonAnimation != null)
    {
        _lastAnimation.gameObject.SetActive(false);

    StartCoroutine(ShowRoseAnimation());
}
}

private IEnumerator ShowRoseAnimation() {
    yield return new WaitForSeconds(DelayBeforeRoseAnimation);
    _roseAnimation.SkeletonAnimation.gameObject.SetActive(true);
    var roseAnimation = _roseAnimation.SkeletonAnimation.GetComponent<SkeletonAnimation>();
    roseAnimation.AnimationName = _roseAnimation.AnimationName;
    roseAnimation.AnimationState.Complete += (t) => _anim.Play("GameManagerFadeMusicOut");
}

Thanks for the additional info.

mstie wrote

The method below is added to the previous animation's (_lastAnimation) complete event.

It seems as if you have not included this part in your posted code, could you please post the complete relevant parts?
Are you sure that you're not accidentally using AnimationState.Complete instead of TrackEntry.Complete? Note that AnimationState.Complete will be called for every completed animation, not the last enqueued one. The line that you have posted is calling _anim.Play() for all subsequent completed loops of any animation:

roseAnimation.AnimationState.Complete += (t) => _anim.Play("GameManagerFadeMusicOut");

So you might want to use code like the following:

TrackEntry trackEntry = skeletonAnimation.AnimationState.SetAnimation(..);
trackEntry.Complete += ..;

instead of:

skeletonAnimation.AnimationName = ..;
AnimationState.Complete += ...;

Oh they absolutely used AnimationState.Complete

_lastAnimation.AnimationState.Complete += AnimationState_Complete;

I'll update it to use trackEntry.Complete instead and see how that affects it.

Thanks for the help

You're welcome, great to hear we've found a potential source of error.

It turns out the issue is still happened even after subscribing to the trackentry.Complete event.

I've included the unity component configurations of these in case anything seems out of the ordinary.

If nothing looks out of place we'll just split up all the animations into separate ones and see if that corrects the problem.

Again, thanks for your help.

Sorry to hear that the issue still persists. Your component configurations all look normal.

Could you please create a minimal Unity project that still shows this error, you can send it as a zip package to contact@esotericsoftware.com (birefly mentioning this forum thread URL so that we know the context), then we can have a look at it.