Using navmesh with custom controller

I have created a custom controller for my units and now I would like to use the NavMesh system to provide a path to those units.

I do not want to simply use the NavMeshAgent system to move the unit because I need more functionality than that. Like for example, falling in holes or flying which would not be on the areas of the navmesh.

How can I get the path that my unit needs to follow to a certain destination from the NavMeshAgent? I would then use this path to know about the movement I must do every frame. This path needs to be updated if obstacles are blocking the way.

CustomController.Move(Vector3 _movement);

Flying is easy to implement with navmesh by just adding vertical offset to the agent and it also allows to make certain areas of your level (border, for example) non-flyable. However if you want custom movement, you just get path from navmesh using Unity - Scripting API: AI.NavMesh.CalculatePath

1 Like

And when you get this path, how do you get the next frame’s movement from it?

Like you would do with any way point system, it’s just a list of ordered points. Unity - Scripting API: NavMeshPath

Ie:

  • find closest corner (first on the list?)
  • find direction toward the closest corner,
  • check the distance to the corner
  • if close and last point, then stop
  • if close to point, then set next point
  • else move toward*stepLength
  • loop

Yes I did this but I realized that despite following the path correctly I had problems with NavMeshAgent not being exactly where my controller is. This was due to my controller moving slightly differently from the NavMeshAgent.

Setting NavMeshAgent.updatePosition = false is a necessity for moving with a custom controller.
I tried a lot of different methods by warping or sampling the path but the best one by far is the one proposed on this page of the forum by a unity dev:
https://discussions.unity.com/t/559089

using UnityEngine;
public class MoveRigidbody : MonoBehaviour {
   Rigidbody rb;
   NavMeshAgent ag;
   void Start () {
     rb = GetComponent<Rigidbody>(); 
     ag = GetComponent<NavMeshAgent>();
     // Disable agent control of the transform
     ag.updatePosition = false;
     ag.updateRotation = false;
   }
  
   void Update () {
     // Move rigibody by agent velocity and update agent position
     rb.velocity = ag.velocity;
     ag.nextPosition = rb.position;
   }
}
2 Likes

Oh yeah I always avoid that part of the system, it annoys me. Sorry.