I'm trying to work local avoidance with root motion

  • A* version: [5.2.4]
  • Unity version: [2022.3.40]

 protected override void Start()
    {
        base.Start();

        AI.canMove = false;
        AI.updatePosition = true;
        AI.updateRotation = false;
    }

private void OnAnimatorMove()
    {
        if (!IsAnimatorMove) return;

        Vector3 nextPosition = transform.position;
        Quaternion nextRotation = transform.rotation;

        AI.MovementUpdate(Time.deltaTime, out nextPosition, out nextRotation);

        if (!_isSpecialAttack)
        {
            nextRotation = animator.rootRotation;
        }
        nextPosition.x = animator.rootPosition.x;
        nextPosition.z = animator.rootPosition.z;

        transform.rotation = nextRotation;
        // Vector3 velocity = animator.deltaPosition / Time.deltaTime;
        // velocity.y = nextPosition.y;

        // _rvoController.CalculateMovementDelta(Time.deltaTime);
        AI.FinalizeMovement(nextPosition, nextRotation);
    }

I’m trying to work local avoidance with root motion, but I can’t see a suitable solution in the forum. I know it’s a top-down relationship, but could you please tell me the next best option?

@aron_granberg

EDIT :

private void OnAnimatorMove()
    {
        if (!IsAnimatorMove) return;

        Vector3 nextPosition = transform.position;
        Quaternion nextRotation = transform.rotation;

        AI.MovementUpdate(Time.deltaTime, out nextPosition, out nextRotation);

        if (!_isSpecialAttack)
        {
            nextRotation = animator.rootRotation;
        }
        // nextPosition.x = animator.rootPosition.x;
        // nextPosition.z = animator.rootPosition.z;
        nextPosition.x = transform.position.x + (animator.deltaPosition.x * Time.deltaTime);
        nextPosition.z = transform.position.z + (animator.deltaPosition.z * Time.deltaTime);

        transform.rotation = nextRotation;
        // Vector3 velocity = animator.deltaPosition / Time.deltaTime;
        // velocity.y = nextPosition.y;

        var delta = _rvoController.CalculateMovementDelta(transform.position, Time.deltaTime);
        nextPosition += delta;

        // transform.position = nextPosition;
        AI.FinalizeMovement(nextPosition, nextRotation);
    }

I think it’s okay to do this, is there any problem with doing it like this?

Was this successful for you? If so I’d say it looks good to use. I was going to suggest RVOController.velocity which isn’t too different from using CalculateMovementDelta at the end of the day in this situation. Maybe CalculateMovementDelta is better though because of this note:

This is not necessarily the velocity the agent is actually moving with (that is up to the movement script to decide) but it is the velocity that the RVO system has calculated is best for avoiding obstacles and reaching the target.

AI.maxSpeed = (animator.deltaPosition / Time.deltaTime).magnitude;

I added this line and it probably works. I’m not sure if it’s the right way.
Is it correct that the code above moves at the speed of the root motion?

Hi

Local avoidance and root motion are pretty hard to combine.
The reason is that root motion wants to control the agent’s movement exactly in order to avoid foot sliding and similar things, and local avoidance also needs to control the agent’s movement exactly for the algorithms to work.

The best thing is typically to set updatePosition and updatePosition to false, and then use the root motion to try to get to the same position/rotation as the agent (you can access its current position using ai.position). But it’s not trivial to get something good looking here.