??
protobot

- 11 May 2022
- 22 Nis 2022 tarihinde katıldı
- [Pixi-spine][2.1.14] Problem Mixing animations tartışmasında
- [Pixi-spine][2.1.14] Problem Mixing animations tartışmasında
Thanks Mario! We appreciate you going through the tedious trouble of finding the implementation bugs. At least now we know where the issue is coming from.
- [Pixi-spine][2.1.14] Problem Mixing animations tartışmasında
Hi Mario,
setTimeout is used only to demonstrate what happens when we pause the pixi ticker and then sequentially call the spineInstance.update function. We don't use it in out app. Various events can request the playback to jump to a given time.
Also, fast forwarding cannot happen inside pixi rendering loop because it's ticker is stopped.
Whatever causes this bug, we suspect has to do how path constraints are implemented in the pixi runtime. Our work around right now is to avoid path constraints. In that case the runtime functions as expected. Path constraints is a nice feature though, would be a shame if we can't use it. - [Pixi-spine][2.1.14] Problem Mixing animations tartışmasında
hi Mario. I am working with warmanw on this project.
We were able to create a much smaller version of the project and reproduce the issue.
It's deployed here for your convenience.
http://cupid-demo.s3-website-us-west-2.amazonaws.com/We are building a spine player of sorts and need to be able to jump to any frame in the animation sequence, i.e. fast forward to a given time mark.
At a high level, we stop the pixi app ticker and jump to a given time by manually updating the spine asset instance by small increments, until it reaches the desired time mark.Here is the code. Pls let us know if you need anything else. Thank you for your input!
import 'pixi.js'; import 'pixi-spine'; function fastForwardSpineInstance({ pixiSpineInstance, // fast forward amount in seconds amount, deltaStep = 0.01, }) { for ( let currFastForwardAmount = 0; currFastForwardAmount < amount; currFastForwardAmount += Math.min(amount - currFastForwardAmount, deltaStep) ) { pixiSpineInstance.update(deltaStep); } } const mixDuration = 0.2; const animationEnd = 0.3; const timeScale = 2; const tracks = [ [{ anim: 'body/idle' }, { anim: 'body/shake' }], [ { anim: 'head/face/talk/graphemes/a', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/b', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/l', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/u', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/w', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/a', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/b', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/l', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/u', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/w', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/a', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/b', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/l', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/u', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/w', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/a', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/b', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/l', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/u', animationEnd, timeScale }, { anim: 'head/face/talk/graphemes/w', animationEnd, timeScale }, ], ]; function jumpToTime({ time, pixiSpineInstance, ticker }) { pixiSpineInstance.state.setEmptyAnimations(0); pixiSpineInstance.lastTime = Date.now(); ticker.update(); tracks.forEach((track, trackIndex) => { pixiSpineInstance.state.setEmptyAnimation(trackIndex, 0); track.forEach((clip) => { const trackEntry = pixiSpineInstance.state.addAnimation( trackIndex, clip.anim, false, 0, ); trackEntry.mixDuration = mixDuration; if (clip.animationEnd) { trackEntry.animationEnd = clip.animationEnd; } if (clip.timeScale) { trackEntry.timeScale = clip.timeScale; } }); }); fastForwardSpineInstance({ pixiSpineInstance, amount: time, }); ticker.update(); } export default function loadPixiApp(app, isPlayBroken) { function onAssetsLoaded(loader, resources) { const pixiSpineInstance = new PIXI.spine.Spine( resources.resource.spineData, ); pixiSpineInstance.x = 400; pixiSpineInstance.y = 575; pixiSpineInstance.scale.set(0.4); app.stage.addChild(pixiSpineInstance); if (isPlayBroken) { // We need to be able to jump to any point in our sequence. // When we want to immitate a controlled playback, we stop the ticker // then jump to the next frame one by one. // That's when it breaks. // Without the code below, it doesn't break. let currentTime = 0; const targetTime = 3; const step = 1 / 30; const waitTimeInMs = 10; app.ticker.stop(); setTimeout(function scheduleNextStep() { if (currentTime < targetTime) { jumpToTime({ time: currentTime, pixiSpineInstance, ticker: app.ticker, }); currentTime += step; setTimeout(scheduleNextStep, waitTimeInMs); } }, waitTimeInMs); } else { jumpToTime({ time: 0, pixiSpineInstance, ticker: app.ticker }); } } app.loader.add('resource', 'cupid/Cupid.json').load(onAssetsLoaded); }