Open jmlee2k opened 7 years ago
The reason this breaks is because pixi spine is doing calling update () in the autoUpdateTransform function. Pixi.js is looping through it's children during its updateTransform function, so if you add/remove children during that loop, things break. In this case, the autoUpdateTransform calling update() causes events to fire, and if you remove/add children it will break pixi.js loop.
So there's 2 solutions. 1) set the spine anim autoUpdate = false, and then call update manually yourself somewhere in your game loop.
2) Fix pixi spine so it uses PIXI.js shared ticker instead of calling update () during the autoUpdateTransform function.
something like this.
Object.defineProperty(Spine.prototype, "autoUpdate", {
get: function () {
return (this._setTicker);
},
set: function (value) {
this.updateTransform = PIXI.Container.prototype.updateTransform;
if (value)
{
if (!this._setTicker)
PIXI.ticker.shared.add (this.updateTick, this);
}
else
{
PIXI.ticker.shared.remove (this.updateTick, this);
}
this._setTicker = value;
},
enumerable: true,
configurable: true
});
Spine.prototype.updateTick = function (tickerDeltaTime)
{
this.update (tickerDeltaTime / PIXI.ticker.shared.speed / PIXI.settings.TARGET_FPMS * 0.001);
}
autoUpdateTranform function isn't used at all in this example modification.
You'll probably also want to listen for 'added" and 'removed' events from pixi and add/remove the shared ticker handler as appropriate so it isn't updating spine animations that isn't added to the scene.
Thanks, If you make a PR, I'll be happy to try it out to see if it works.
The problem is that pixi has no "added to stage" or "removed from stage" events.
Vote for it: https://github.com/pixijs/pixi.js/issues
Until i fixed, you have to do it on your own. autoUpdate works only in simple cases :(
Any updates ?
Does anyone have a complete working fix for this? I need to make my spine visible and start an animation in the same frame, but this does not seem possible. @albymack Do you have the complete code including the "added" and "removed" events that I could use as a workaround for this bug? I've been stuck on this for quite a while and haven't really made any progress. Thanks!
Which version do you use ? try update to latest (from bin folder of this repo)
but yeah, nobody solved it, and there's no animation system in pixi, its user job to implement it for their app.
good idea :)
I changed updateTick to the following and it seems to work, now it only updates when the spine is visible:
Spine.prototype.updateTick = function (tickerDeltaTime){
if(this.worldVisible){
this.update (tickerDeltaTime / PIXI.ticker.shared.speed / PIXI.settings.TARGET_FPMS * 0.001);
}
};
I had some issues with the fix above that caused flickering on screen, but I think I found another way to solve the problem. I only tried it on a test case so far and it seems to work but I will try it on my main project tomorrow.
var oldRender=PIXI.Application.prototype.render;
var defferedAnimations=[];
PIXI.Application.prototype.render=function(){
oldRender.apply(this, arguments);
for(var i=0;i<defferedAnimations.length;i++){
var anim=defferedAnimations[i];
anim.func.apply(anim.scope, anim.args);
}
defferedAnimations=[];
};
var statePrototype=pixi_spine.core.AnimationState.prototype;
var oldAnim=statePrototype.setAnimation;
statePrototype.setAnimation=function(){
defferedAnimations.push({func:oldAnim, scope:this, args:arguments});
};
Essentially I defer calls to the setAnimation function so that it only gets executed at the end of PIXI's rendering phase (after it has finished calling updateTransform on everything).
First, thanks for all the great work here!
It seems that performing the following sequence of events will cause a spine animation not to play the second time:
In addition, the same thing happens when setting visible to true and false instead of removing and adding the spine object to/from the stage.
I've managed to get it to work by either waiting around 20ms between showing the animation the second time and playing it, or by using requestAnimationFrame. However, both of these methods leave the animation at the last frame for a split second before playing it again.
My guess is that this is some sort of optimization to prevent animations from playing on objects which aren't on the stage or hidden, and it doesn't know that the object is visible / back on the stage until the next JS frame.
I know this is a bit complicated, so I've created a test case which displays the issue at https://jmlee2k.github.io/pixi-spine-anim-test/. You can also view the source at https://github.com/jmlee2k/pixi-spine-anim-test.
Each button will:
I've tried to keep the test case as simple as possible, so please excuse the somewhat brutal code :).
Please let me know if you need any other information.
Thanks in advance!