Using a NavMeshAgent with a CharacterController

Since the Unity docs, Unity Answers, and the wild are a little vague on this, I would like to share how to get a NavMeshAgent and CharacterController to play nice together on an NPC (tested on 5.6). This solution allows the agent to still avoid all defined obstacles and other NPC’s while also respecting other character controllers (such as the player) and any game geometry with colliders on it.

    public class Enemy : MonoBehaviour {

        public Transform _playerTrans;
        public float _speed = 2;
        public float _turnSpeed = 3;

        private NavMeshAgent _agent;
        private Vector3 _desVelocity;
        private CharacterController _charControl;

        void Start() {

            this._agent = this.gameObject.GetComponent<NavMeshAgent>();
            this._charControl = this.gameObject.GetComponent<CharacterController>();

            this._agent.destination = this._playerTrans.position;

            return;
        }

        void Update() {

            Vector3 lookPos;
            Quaternion targetRot;

            this._agent.destination = this._playerTrans.position;
            this._desVelocity = this._agent.desiredVelocity;

            this._agent.updatePosition = false;
            this._agent.updateRotation = false;

            lookPos = this._playerTrans.position - this.transform.position;
            lookPos.y = 0;
            targetRot = Quaternion.LookRotation(lookPos);
            this.transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, Time.deltaTime * this._turnSpeed);

            this._charControl.Move(this._desVelocity.normalized * this._speed * Time.deltaTime);

            this._agent.velocity = this._charControl.velocity;

            return;
        }
    }

The key to making sure they play nice is this:

this._agent.velocity = this._charControl.velocity;

Thanks to AngryAnt for that little gem in post I found. If you do not update the nav mesh agent with the velocity of the character controller post move, unpredictable behavior results.

8 Likes

Thanks man! I was exactly looking for something like this!

Would this also work with a player controller? I mean, can I control my player character with a custom character controller and still use a nav mesh agent to know where it can navigate to?

Sure, it should work with any controller, be it a rigidbody based controller or a custom controller, as long as you update the agent with the velocity the controller sets. That is the critical step to keep the agent functioning correctly.

2 Likes

I am having a conversation in reddit about this. Maybe you’re interested.

https://www.reddit.com/r/Unity3D/comments/66aqop/mixing_nav_mesh_agents_with_thirdfirst_person/

If all you want is for the NavMeshAgent to not update position ever, then you can set that in Awake/Start instead of Update.

void Start()
{
        var navMeshAgent = this.GetComponent<NavMeshAgent>();
        navMeshAgent.updatePosition = false;
}
2 Likes

This doesn’t seem to work for me.
My AI stresses out and flies away.
I use unity 2017.

Has someone tested this in 2017?

1 Like

my ai character still has the zoomies. having it patrol a set of way points which it follows but … yeah something gave it coffee and I do have the

  • this._agent.velocity = this._charControl.velocity;

Disregard. My issue was another script that was setting its velocity

Thank you. Your answer helped me.