Looping skinned mesh animation with "root motion"

Game engines like Unity and Unreal seem to want animation with root motion for animation clips. My understanding is this is simply an additional bone above the hips that captures the character’s translation, i.e. if a character walks 10m in a walk cycle the bone above the hips would translate 10m and the hip bone wouldn’t have any (significant) translation. The alternative is for the animation to walk in place and rely on the game engine to translate the character as it sees fit.

I have a walk cycle with root animation that works fine in the browser, except when it loops it bounces back to the origin. I added a ‘loop’ event handler to the mixer that adds the top level bone Z translation to the skinned mesh position whenever the cycle loops. It looks like it’s working but is this the right process?

Why don’t you just use “in-place” animations? All animated characters of the official examples use this type of animation.

I’m not sure this is correct. Feels a bit like a hack…

I have the same issue: does Three.js support animations (i.e. walk animations) with root motions? Using the above method allows the animation to move smoothly but then slides when transitioning to another animation afterwards.

It’s not really clear to me what’s being described here, and how it differs from what three.js already supports.

I think I would generally expect walking animations to play “in place”, and separate code moves the character around the scene, so that e.g. you can switch between walk and run animations without affecting the position of the character. Is that different from what “root animation” refers to?

Root motion means the animation also moves the position of the root bone (i.e. the position of the character) during the animation. Many walk animations do this The majority of walk animations (if not all of them) available from reallusion.com (Icone) for example include root motion. So do the walk animations from Mixamo unless explicitly exported with root motion turned off. Three.js can’t use any of these walk animations unless there’s a way to handle this.

Even so, I don’t think Root Motion the most common or practical way to use these files in three.js. This option should be turned off by most users, even if we did support Root Motion.

But this seems like a feature request worth considering, if you’d like to write up an issue on GitHub. I think it would be necessary to explain in more detail what should be happening in the animation system, as opposed to what is happening now, the term “Root Motion” still does not really explain that to me. More specifically — what happens when animations using Root Motion are looped and blended?

I’m also not sure if this fits into the current AnimationClip / AnimationMixer system, or requires something more like Blend Trees (Blend Trees · Issue #6935 · mrdoob/three.js · GitHub).

I found this explanation of root motion very helpful —

Here’s what you need to do eventually in practice:

  1. Precalculate the average velocity of the root bone during one cycle of the animation (end pos - start pos / duration).
  2. Bake your animation data with that velocity subtracted from the root bone’s translation keys. So, the animation ends up looking like he’s animating while standing on a constant-speed treadmill pushing him back where he started.
  3. When animating in the game, apply the animation’s extracted velocity to the root of the character. Now the animation looks correct in game and the root moves around.

Bonus: Find the ratio of the speed of the animation’s extracted velocity vs. the character AI’s desired speed. Use that to scale the playback speed of the animation. That way the feet won’t slide even when the character walks at a different speed than the animation was originally designed for.

https://www.reddit.com/r/opengl/comments/e9noi8/hello_guys_i_am_trying_to_add_root_motion_support/


If that all sounds correct, I think what we could do would be to provide a new method in AnimationUtils or SkeletonUtils, that extracts the root motion from a given AnimationClip, modifies the clip to run in place, and returns the average velocity associated with the clip? It would be up to your application to decide how to apply the average velocity.

const velocity = THREE.SkeletonUtils.extractRootMotion(
  skeleton,      // THREE.Skeleton
  targetClip,    // THREE.AnimationClip
  targetVelocity // THREE.Vector3
);
1 Like

This would be extremely helpful. Especially for animations like vaulting over objects or climbing up a ledge. These kinds of animations are never “in place”. They hacky way I’ve been doing this for along time now is just trial and error: see where the character ends up, manually figure out the coordinates and teleport the character object to the new location immediately as the next animation starts playing…

I think a parameter on an animation clip that dictates that the mesh should be translated (or not) along the root bone would be the most intuitive way to go IMHO.

I can’t see a practical way for THREE.AnimationClip to have that kind of control over the root bone, without a lot of assumptions the animation system does not currently make about the content of your scene and animation, and major changes to the animation system. Probably this would be a reason Unity would be doing all of this as a build step, and compiling the animations down to something more like our current animation system. Possibly that could fit into a blend tree system, if something like that were added to three.js in the future (Blend Trees · Issue #6935 · mrdoob/three.js · GitHub).

If it’s enough for the average velocity to just be extracted from the clip and returned separately, to be applied by whatever system you’re using to transition between animations now, I think we can implement that without much trouble.

1 Like

Could someone share a file (.FBX or .GLB maybe) with an animated character requiring root motion?

Sure, here’s one straight from Mixamo.

Sprint To Wall Climb.fbx (1.8 MB)

1 Like

Thanks! Feedback welcome:

1 Like

I found a way to turn root motion into in-place animations. The way i do it is install Blender, and this addon:

It works well. If you download a root motion animations, then you can simply convert it to in-place! I hope this helps anybody :slight_smile: