Setting currentTime breaks animation

Hi,

I’ve been experimenting with animations - more specifically, starting them from a specific point. However, I’ve run into a problem when setting currentTime, where the animation is interpreted wrong. Here’s an example:


Above you can see the keyframes of an object. It is animated in two stages. First a large piece is rotated up. Second a small piece, parented to the first piece, is rotated back.

Now, say I want to set currentTime to 0.45. You expect to see the large piece rotated up fully, and the small piece half way rotated. But this is what I get:


The large piece is stuck at it’s starting position, and the small piece is half way rotated.

What’s going on here? Why is it just ignoring the animation on the large piece?

Here’s the code i use:

var SetCurrentTime = pc.createScript('setCurrentTime');

// initialize code called once per entity
SetCurrentTime.prototype.initialize = function() {
    //Get object
    obj = this.entity;
    
    //Get animation
    var animID = obj.animation.assets[0];
    var animAsset = pc.app.assets.get( animID );
    
    //Initialize animation, but don't start playing
    obj.animation.play(animAsset.name, 0.0);
    obj.animation.speed = 0;
    
    //Set currentTime
    obj.animation.currentTime = 0.45;
};

Here’s a stripped down project, highlighting the error:
https://playcanvas.com/editor/project/606277

At a guess, it looks like one or more of the keyframes isn’t being interpolated when the time is set. I’ve forked the project and going gradually from 0 -> 0.45 through setting the currentTime ‘works’.

I’ve created and did this:

    if (this.app.keyboard.wasPressed(pc.KEY_SPACE)) {
        for (var i = 0; i < 9; ++i) {
            this.obj.animation.currentTime += 0.05;
        }
        console.log(this.obj.animation.currentTime);
    } 

Horrendous but it works mostly for the short term.

Project: https://playcanvas.com/editor/scene/723411

Thanks, yeah I also figured it has something to do with keyframe interpolation. The bone that drives the large piece only has two keyframes: frame 0 and frame 10. When we set currentTime to something beyond frame 10, it doesn’t understand that it should use the last keyframe as its position.

So I did another test, where I added an extra keyframe on frame 20, which I copied from frame 10. Now setting currentTime to 0.45 works correctly, strengthening my theory.

This is less of a ugly hack than looping and incrementing currentTime, as you did above. However, it’s still just a workaround. This issue isn’t obvious for artists/devs, and is most likely an oversight in the animation system.

For my current project, I can manage with this workaround since its animations aren’t all that complicated. But I think fixing the root cause is the best approach.

1 Like

If your animation app gives the option, you might consider baking motion envelopes or baking motions when exporting the FBX. What that typically does is create a keyframe at every frame step for all motions.

1 Like

I’m using 3ds max. When exporting FBX, “Bake Animation” is usually enabled. I figured that would do it. Apparently though, it only bakes unsupported animations (constraints, IK, wire params, etc.) - simple bone transformations are never baked.

What you also have to enable is “Resample All”, which bakes all animations. I just tried it, and it fixes the problem with setting currentTime, without having to manually copy keyframes.

The downside of this approach is, of course, larger animation files: 0.69 KB vs 4.32 KB in my example. With sizes this small, it’s not a problem. But it might be something to keep in mind when doing longer animations.