Spinning AI Agent Bug(And Fix)

TimTheTerrible

New member
I was making some prototyping enemies out of some some character assets from the unity asset store. They are scaled way to big out of the box, so I scaled them appropriately and made them in to UCC characters.

When they actually are walking to a destination they act fine, but sometimes when arriving at there destination they would start spinning really fast on the spot, like ballerinas on crack... Anyway, I THINK I have found where the error lies, it is inside the ApplyPosition() of the NavMeshAgentMovement ability.

Original code:

Code:
        public override void ApplyPosition()
        {
            if (m_NavMeshAgent.remainingDistance < m_NavMeshAgent.stoppingDistance) {
                // Prevent the character from jittering back and forth to land precisely on the target.
                var direction = m_Transform.InverseTransformPoint(m_NavMeshAgent.destination);
                var moveDirection = m_Transform.InverseTransformDirection(m_CharacterLocomotion.MoveDirection);
                if (Mathf.Abs(moveDirection.x) > Mathf.Abs(direction.x)) {
                    moveDirection.x = direction.x;
                }
                if (Mathf.Abs(moveDirection.z) > Mathf.Abs(direction.z)) {
                    moveDirection.z = direction.z;
                }
                m_CharacterLocomotion.MoveDirection = m_Transform.TransformDirection(moveDirection);
            }
        }

The problem I believe is the call to m_Transform.InverseTransformPoint. It would be fine if the scale was at (1,1,1), which for the most part my models usually are or have been up to this point when using the nav agent. But if the scale isn't at (1, 1, 1), the InverseTransformPoint will change the result of the calculation to something we don't want. The fix:

Code:
        public override void ApplyPosition()
        {
            if (m_NavMeshAgent.remainingDistance < m_NavMeshAgent.stoppingDistance) {
                // Prevent the character from jittering back and forth to land precisely on the target.
                // Super lazy way of doing it but hey don't judge!(temporarily store scale of character, set scale to one, do the inverse transform, then restore the scale.) 
                var scale = m_Transform.localScale;
                m_Transform.localScale = Vector3.one;
                var direction = m_Transform.InverseTransformPoint(m_NavMeshAgent.destination);
                m_Transform.localScale = scale;

                var moveDirection = m_Transform.InverseTransformDirection(m_CharacterLocomotion.MoveDirection);
                if (Mathf.Abs(moveDirection.x) > Mathf.Abs(direction.x)) {
                    moveDirection.x = direction.x;
                }
                if (Mathf.Abs(moveDirection.z) > Mathf.Abs(direction.z)) {
                    moveDirection.z = direction.z;
                }
                m_CharacterLocomotion.MoveDirection = m_Transform.TransformDirection(moveDirection);
            }
        }
 
Thanks for posting your fix. Have you tried increasing the stopping distance of the NavMeshAgent? This should also stop the spinning.
 
Yes I tried both increasing the stopping distance in the nav agent component and on the ability itself. The spinning doesn't happen if the character is at a normal scale, but if i modify the scale it happens for different values. The characters I used had to be shrunk down to about 0.25 of there normal size.
 
Top