Spine Plugin - Animation Complete Callback

Hi there,

Short: How can I trigger an event after a animation has finished playing using spine in PlayCanvas?

Long: In the old Version of Spine one could add a “onComplete” Callback, e.g. to play animation “Walk” after animation “Attack” has finished. This is from an old example:

this.entity.spine.state.setAnimationByName(0, "Attack", false);
                this.entity.spine.state.onComplete = function (track, count) {
                    if (this.tracks[0].animation.name === "Attack") {
                        this.setAnimationByName(track, "Walk", true);

I am aware that the “setAnimationByName” was renamed to “setAnimation”.

But I think the “onComplete” function is gone. Is there an equivalent for the “onComplete” action? How can I trigger some events when a specific animation has ended? Most preferably by a proper callback, not by some hacks like checking the state every frame or something similar…

Thanks for your help,

I haven’t heard of this “Spine” API. Where did you find it? I’m curious as to what it does?

It’s a wrapper (click) to use animations created with a tool named “spine” (click) within PlayCanvas engine.

It’s a 2D animation system?

Yes. In their Pro Version they also feature pretty awesome “2.5D” mesh deformations, check it out here: http://esotericsoftware.com/spine-demos


this proved a pain in the butt to figure out for me too - the Spine API docs are too long winded. Basically it’s something like a ‘delegate’ pattern now.

Here’s my animation control script, which adds hooks to get events, end and the like:

var AnimationController = function(ent)
    this.entity = ent;
    this.paused = false;
    this.playing = false;
    this.speed = 1;
    this.delegateObj = {
        start: this.onStart.bind(this),
        complete: this.onComplete.bind(this),
        event: this.onEvent.bind(this),
        interrupt: this.onInterrupt.bind(this),

AnimationController.prototype.getMainTrack = function(){
    return this.entity.spine.state.tracks[0];

AnimationController.prototype.setPlaybackSpeed = function(speed){
    this.speed = speed;
    if( this.getMainTrack() ) this.getMainTrack().timeScale = this.speed;

AnimationController.prototype.play = function(name,speed,loop){
    this.playing = true;
    this.paused = false;
    this.entity.spine.state.setAnimation(0, name, typeof loop != 'undefined' ? loop : false);
    if( typeof speed != 'undefined' ) this.setPlaybackSpeed(speed);

AnimationController.prototype.stop = function(){
    this.playing = false;
    this.paused = false;

AnimationController.prototype.pause = function(){
    if( ! this.playing ) return;
    this.paused = true;
    this.getMainTrack().timeScale = 0;

AnimationController.prototype.resume = function(){
    if( ! this.playing ) return;
    this.paused = false;
    this.getMainTrack().timeScale = this.speed;

AnimationController.prototype.destroy = function(){
    this.entity = null;
    this.delegateObj = null;

AnimationController.prototype.onStart = function(track){

AnimationController.prototype.onComplete = function(track){

AnimationController.prototype.onEvent = function(track,event){

AnimationController.prototype.onInterrupt = function(track){

Note that this script is independent from the PlayCanvas script system - you create a new AnimationController, and pass it your Spine entity. Then you control the Spine anim via the API presented on the AnimationController here.


Thanks a lot @inductible - Those snippets helped me out :wink:

Have a nice day,

1 Like