Correct way to handle root motion with parent game object

So I have a parent game object which is just a container and has all the components included, such as Animator and RigidBody etc. Now one of its children is a humanoid model, lets call them PlayerContainer and the child PlayerModel.

The problem I have is that the root motion seems to be applying to the PlayerModel not the PlayerContainer, now I know there is the OnAnimatorMove event, but I am not entirely sure if I even need this callback on the parent as it seems a bit of a hack to have to keep resetting the parent position to that of the child then resetting the child position each time.

So I assume this is a common thing where animators are on parent objects with the mesh models as children, so is there a special way to get root motion acting as expected here where it moves the root object opposed to the model?

OnAnimatorMove is your friend. Implement it on a component attached to the same GO as the Animator and then forward the call to your movement component on you root GO, where you can apply movement via yourAnimator.deltaPosition.


To clarify for new questions here:

  1. On your child object with the animator, implement a script (you could call it AnimatorForward) with OnAnimatorMove which calls OnAnimatorMove on a target parent script.
  2. In the OnAnimatorMove on that target script on your parent, apply Animator.deltaPosition to your current position - literally transform.position += myAnimator.deltaPosition;
  3. Profit!

I hope that clears any lingering doubt.

Hello. I have a vaguely related problem that I thought I might talk about here in case someone encounters it.

When you use root motion with your own playables system, and you have animations that loop, you will see that your final skeleton will jump back.

I believe that the Animator is secretly aware of WHEN an animation loops, and at this point it increments skips passing on the “back to the beginning” delta, so that you get an uninterrupted accumulation on rootPosition and rootRotation.

But, if you are making your own playable, the system isn’t implicitly aware of this going on, so you must cope with it manually.

In my case, I have the normalized time of my entire blend tree system, and can monitor the moment that it goes from >0.5f to <0.5f. On this frame, I just re-use the previous frame’s delta, instead of the given delta (which would jump my character back to where they began).

I hope this helps someone.

I’ve been grappling with a desire to try to remotely move multiple Avatars by remotely referencing their Rigidbodies/AnimatorControllers. But on a recent error it was pointed out to me that the OnAnimatorMove function only inherits from this as in this.gameObject(the one its expected to be directly attached to).

And while its entirely possible to remotely reference and allow multiple gameObject transforms to be controlled through a single script with a for loop( like say for multiplayer game?) I haven’t as much success with doing the same with rigidbodies.

My understanding of Rigidbodies however is that they are each directly attached to their own respective CapsuleCollider. As such since each Capsule Collider also has its own Collison functions, this suggests that you must have a script attached to each gameObject for those components which possibly extends to the animator controller.
I could imagine (and had coded an alternative way) that uses arrays to grab/store/reference multiple AvatarGameObjects, Rigidbodies, and AnimatorControllers but Unity apparently based on the reasons mentioned above does not support this.

All that is to say OnAnimatorMove is a singular object function hence a networked(cleaner code) implementation isn’t really supported at all.

Which in retrospect makes sense. If it was an online game who exactly would control what avatar. Locally however this should be fine and allowed. Think about all those multiplayer arcade games or multiplayer home console games.

Seems like the container is the problem here.

Removing the container and applying the components to the character directly will allow root motion to work correctly.
Or am I missing something from the above information?

Unless the mixamo animations do not have root motion to begin with.

All the Solutions mentioned above will always be “Catch up and Reset” whenever you have a child object moving.

To avoid this cat and mouse chase and reset, the child object must NEVER move. Instead, turn off the root motion on the child , Copy its animator component, and paste it into the Parent Object. With this, you will notice the parent object now moves correctly according to the applied Root motion data; however, the child object contains its own animator and it will remain uninfluenced.

You will need to create a script to Sync both animator triggers. The Parent animator will allow your NavMesh Agent to move correctly, but the challenge is to make sure your Child Object animator is playing on the same speed and frame of the Parent Animation.

Summary: Avoid Cat and Mouse, and change it up to a challenge of Animation Synchronization. One must be aware that this now leads to a funky problem on slow, failing, and struggling machines. Your Parent will always trigger before your child. If the computer fails or slows down on the frame between the triggering of your Child and Parent, the appearance and travel will produce different results until both are told to stop. In different words, The child object is now a visual, and your parent is now the root motion object.