Help: Root Motion combined with RVO

I’m currently trying to get mechanim’s root motion to cooperate with the RVO avoidance controller, and I"m having no such luck.

I’ve read into a couple of older post being:

Mecanim and RVO, and
Disable position update in rvo controller.cs

None of which had really a solution.

The closest I have come to something functional is using the desired velocity passed to the rvoAgent. Unfortunately, it avoidance doesn’t seem to be working using this method. My test scene is setup with two AI players starting opposite to one another, and they have to pass by to the other’s starting positing. When they meet in the middle, they become stuck and the avoidance doesn’t seem to be kicking in.

I’m curious whether anyone has found a way to integrate the two since these posts are over a year old now.


This is a lot easier with the latest beta version. In the beta version, the RVOController no longer handles movement by itself, instead you use some movement script which can query the RVOController for how it should move during that frame in order to avoid other agents. The movement script may deviate from this (for example using root motion) with some reduction in avoidance quality as a result. So I encourage you to try the beta version and see if you can get it working there. Personally I haven’t tried to apply root motion to it yet.

See also the code sample here:

Awesome! Thank you very much @aron_granberg!

Is the CalculateMovementDelta method the new one that could possibly be combined with root motion?

Yes, that is correct.

Perfect! I will try this out when I get a chance :grinning:

Thank you once again!

Got around to hooking in my character with root motion and it works very well! No more collisions between agents :slight_smile: thanks once again @aron_granberg

On a side note, do you know what causes agent to sometimes take an arcing path to their target? I’ve notice that sometimes they seem to wonder great distances indirectly to their target when their are no obstructions and have a clear path straight to their goal.


If you are using a recast graph, this is unfortunately one of the side effects of navmesh based graphs when using pathfinding on the triangle centers. The path is not always optimal.
See this page for some discussion about it:

I’ve been trying to get this to work properly for a couple of days now, but unfortunately I’m not having much luck. The character’s feet constantly look like they are sliding. Is there any chance you could share what you did to achieve root motion with RVO?

I have the same problems. So I’d love to see your solution too :slight_smile:

Any updates from other people on getting root motion to work properly with richAI + RVOController? I’m using the 3.8.5 rvo beta version, but I’m having problems getting everything to sync up.

My intent is to calculate current speed (movement and rotation) as calculated through RichAI (somehow) and to pass them as parameters to Mecanim during Update. Then I want to use the delta position/rotation from the animation controller to keep things synced with OnAnimatorMove().


   void OnAnimatorMove() {
      Vector3 vel = m_AIAnimator.deltaPosition / Time.deltaTime;
      // But what do I do here???

The CalculateMovementDelta example in the docs doesn’t seem to be tied to root motion itself, and my hacking away at things doesn’t seem to be getting me any closer to a working solution. Suggestions?

Did you ever find a solution to this challenge?

Just to come back to this topic. Using the new 4.2.5 version of the package I managed to get a fairly good solution.

In my controlling script I do roughly the following:

private AIBase ai;
private Animator anim;

void Initialize()
  ai.updatePosition = false;
  ai.updateRotation = false;
  ai.canMove = false;

void UpdateAI(float deltaTime)
  Vector3 nextPosition;
  Quaternion nextRotation
  ai.MuvementUpdate(deltaTime, out nextPosition, out nextRotation);
  Vector3 deltaPosition = nextPosition - this.transform.position;
  Vector3 velocity = deltaPosition / deltaTime; // deltaTime is never 0 in this method
  float vx = Vector3.Dot(transform.right, velocity);
  float vy = Vector3.Dot(transform.forward, velocity);
  anim.setFloat("veloctyX", vx);
  anim.setFloat("velocityY", vy);

/// You could also use OnAnimatorMove()
void LateUpdate() 
  ai.FinalizeMovement(anim.rootPosition, anim.rootRotation);

(note that this is code translated from several spots in the code-base and there might be a small error)