engine
engine copied to clipboard
AnimEvents not dispatched after activeStateCurrentTime updated
Project : https://playcanvas.com/project/970223/overview/debug-seeking-animation
I want to be able to seek inside an animation. For now i just use activeStateCurrentTime.
For the use-case :
- i have added manually 3 AnimEvents of type "trick_step" with code in anim.js file
- an AnimEvent of type "animation_frame" is added for each 0.1s of the duration of the animation
- a final AnimEvent for the end of the animation (type "animation_end")
Steps to reproduce the working use-case :
- open JS console
- click on "load ollie"
- wait a little, you should see logs of AnimEvents frames, and the animation will stop on event "trick_step" with status "step_0"
- click on play, animation continue to event "trick_step" with status "step_0b"
- click play , and animation continue to event "trick_step" with status "step_1"
- click on play and after the animation ends.
Steps to reproduce the issue :
- click on "load ollie"
- wait a little, the animation will stop on event "trick_step" with status "step_0"
- click on "Next 2.7", the animation move to event "trick_step" with status "step_0b "(i just updated activeStateCurrentTime)
- click on play and after the animation ends but no logs for AnimEvents. But it is strange, they restarted a few seconds later...
Looks like there is an issue where it's possible for the anim clip this.eventCursor
to be out of sync with the anim layer activeStateCurrentTime
causing this line to fail:
https://github.com/playcanvas/engine/blob/main/src/anim/evaluator/anim-clip.js#L119
eg. If the animation is stopped on 2.6 secs and this.track.events[this.eventCursor].time
is 2.6 When the activeStateCurrentTime
is moved to 2.7, this line fails because the next event that is being targeted is in the past.
Here is my questionable workaround for this that advances the eventCursor forward when the time is set: https://playcanvas.com/project/972398/overview/f-debug-seeking-animation
Anim.prototype.nextStep = function(time) {
console.log(time);
const floatTime = parseFloat(time);
this.entity.anim.baseLayer.activeStateCurrentTime = floatTime;
// Work around that really shouldn't be used (+_+)
// Get to the animation clip(s) and advance the eventCursor forward
const clips = this.entity.anim.baseLayer._controller._animEvaluator._clips;
for (let i = 0; i < clips.length; ++i) {
const clip = clips[i];
if (clip.blendWeight > 0.0) {
while(clip.track.events[clip.eventCursor] && clip.track.events[clip.eventCursor].time < floatTime) {
clip.eventCursor++;
}
}
}
};
@ellthompson If you need help or enhancements on my repro project, don't hesitate to ping me.
Any news ? thanks
This looks like a bug in the AnimClip class. The clip's eventCursor is currently being aligned to the initial time of the clip in the class constructor. We should also be realigning the cursor whenever the a clip's time property is updated externally. I'll submit a PR to fix this tomorrow after testing this a bit more.
Cool thanks for the quick fix. I will have a look and see if it works on my use-case.
@ellthompson I confirm the fix works well ! Thanks 🙏🏻