• Bugs
  • AnimationState and TrackEntry End event not firing

According to this page:
Coding for Spine Events and AnimationState callbacks

The End event is fired when an animation is interrupted, when it ends and another animation follows and when it ends being the very last animation.
Unfortunately End is NOT fired at the very End

When I replicate the image shown at the link in code I get an End call after the interrupt and where the followup animation is (End 1 and 2), but I'm not getting an End paired with the Complete at the very end (End 3)

Related Discussions
...
  • Изменено
Alexees написал

Unfortunately End is NOT fired at the very End

When is the "very end"?

From the page you linked, under End:

Note that by default, non-looping animation TrackEntries do not stop at the duration of the animation. Instead, the last frame continues to be applied indefinitely until you clear it or some other animation replaces it. See below for more information on how to make this behave differently.

I'm not sure what "see below" should be referring to. @Harald, can you check that out?

The precise definition for when the AnimationStateListener events are fired is here:
AnimationStateListener

It sounds like you want the track to be cleared when your TrackEntry reaches its animation duration. To do that, set TrackEntry trackEnd to the animation duration. See the note for AnimationState setAnimation.

End would have been perfect to register to if I wanted to make dead sure that I get an event no matter how an animation ends. In that one particular case it's the last non-looping animation, it's not. So I guess I need to register to End and Complete if I want that behaviour?

The timeline image is misleading though. The End event should not appear at the end (or mention in brackets that it's only fired if the track's cleared afterwards, although I don't know who would want to do that if whatever animation then freezes)

Registering a listener doesn't affect playback behavior. You'd need to set the trackEnd time if you want the track cleared. That could be useful eg when an animation changes something and it stays that way, like a door opening.

The end event occurs "when this entry will never be applied again". If you don't want to set trackEnd to clear the track, then it's not the right event for your use case. If you want to do something when the trackTime reaches the animation duration, then you can use the complete event. For a non-looping animation it will only happen once. For looping if you only care about eg the first complete event, you can ignore it if entry.trackTime >= entry.animation.duration * 2.

Depending on your needs, another way to do it could be to queue the next animation. Eg, if you set an attack animation, also add an idle animation after it (or whatever you need, maybe an empty animation to go back to the setup pose). If something else happens, you'd set a new animation and add idle after it. This way you don't need to listen for complete, but means you probably want to set a new animation, not add it to the existing queue (which would go after idle). There is a way to clear an entry from the queue, using AnimationState clearNext, so that could be used to remove idle, then add something else.

I agree, the image shows the behavior as if trackEnd is set, but the code shown doesn't set it. We'll see about improving it.

Thanks for reporting and sorry for the confusion! The documentation page has been updated accordingly.