Bug importing animations making everything 1/30th slower and eating last source frame (jerky looping)

So this is what happens when I import a FBX animation into unreal:

The animation length is 0.666s, FPS is 30, one keyframe every 33ms, which means the frames are [0…20]. The last frame is at length 0.666

  1. The importer DISCARDS the last frame (possibly because it’s at the exact end of the animation). It still reads the animation length as 0.666
  2. The importer now RESAMPLES the animation so that the next-to-last frame BECOMES the last frame that was originally DISCARDED. so [0…19] is resampled into the original times of [0…20]. The animation length is still 0.666, which means the animation is now 1/30th SLOWER than the original.

Here’s proof of that in action:

3dsmax readouts of root bone translation:

UE4 readouts of root bone translation:

As you can see, every frame has been resampled to be 1/30th slower than the original (to keep the time of 0.666 intact, but DISCARD the last frame from the original, and I have no idea why). At 0.666 the movement is now 190 instead of 200.

And don’t tell me I should use ‘Add looping interpolation’, because ALL that does is add ANOTHER frame at the end which is a COPY of frame 0, it doesnt re-scale the animation back. Time 0.666 still has 190 instead of 200, its just that it adds a copy of frame 0 at time 0.7, which now has translation 0, not 200, so it would completely negate root motion extraction from the anim.

It also doesn’t matter what options I use during animation import. Use default sampling rate and changing the ‘Animation Length’ combo box can never get the importer to not drop the last frame (even if i use Set time and enter a larger than 20 value for the end frame).

I’m pretty sure this has been like this ever since whatever change removed the bLooping flag from animation sequences and added in the horrible in-editor hack (who thought that would ever work?), it’s just that I’ve ignored the slight jerk in my looping animations untill I decided to investigate and fix it.

So, what happens if I now take this (wrongly) imported animation in UE4, and EXPORT it back to FBX ?

This is what:

The wrong resampling is still there. So importing an animation into UE4 and exporting it back is a DESTRUCTIVE operation, you can never get that last frame back !

For funsies, let’s now take this UE4 exported animation, and import it back as a new asset:

The last frame has been DISCARDED AGAIN, and now the movement @ 0.666 is even less than before.
So if you keep this up, you will eventually end up with a completely static pose.

Engine Version 4.6.0
I’ve attached the non-destroyed FBXs of the preview mesh and animation
[here (click me)][5]

To reproduce, just import PreviewMesh.fbx as a skeletal mesh and create a skeleton from it, then import the animation Sneak_WalkF using that Skeleton. Frame 20 will have Null bone local movement as 190 instead of 200 like it should (which you can check by importing just the animation fbx into 3dsmax and checking the transform of the Null bone at frame 20).

I submitted a fix in pull request https://github.com/EpicGames/UnrealEngine/pull/670

This came off to be a ‘off-by-one’ error when the animation time is not exactly a multiple of 1/ResampleRate seconds (as pretty much none of them will be). This caused the last frame that should have been sampled to be skipped, resulting in RawKeys having one less entry. Since RawKeys have no timing information on each key, they are just linearly mapped to [0…AnimLength] which results in the slowdown demonstrated above.