Hi, I'm having a strange issue with remainingDistance, where the navmesh agent doesn't seem to be calculating the distance correctly. I have 6 enemies being spawned at the same time, and they are each assigned random waypoints. Two of the waypoints seem hard to get to, but they still are possible according to NavMeshPathStatus, so what happens is that two of my enemies don't move from their spawn point and an if statement checking that the remainingDistance is below 0.1f fires off a function that makes the enemy start firing. It seems like there's some sort of timing issue here, because if I remove the arrivedAtWaypoint in the if statement, the enemies can all get to their waypoints without a problem. Code (CSharp): using UnityEngine; using System.Collections; using DG.Tweening; public class EnemyMovement : MonoBehaviour { [Header("Settings")] public float rotationSpeed = 20.0f; public bool HasRagdoll = false; public bool HasAnimation = false; // temporary solution for characters with no animations yet public float sinkSpeed = 2.0f; [Header("Nav Mesh")] NavMeshAgent nav; public float DistanceToMyWaypoint = 0; public bool IsNavigating = true; public bool IsAttacking = false; public bool arrivedAtDestination = false; public bool DistanceToMyWaypointIsInfinity = false; public bool CanReachMyWaypoint = false; public Transform myWaypoint; // the waypoint private Transform myTransform; [Header("Connections")] // scripts public Transform targetPlayer; public Transform EnemyGun; public Animator EnemyAnimator; // The mecanim animator public HashIDs hash; public EnemyFire enemyFireScript; void Awake () { targetPlayer = GameObject.FindGameObjectWithTag ("Player").transform; nav = GetComponent <NavMeshAgent> (); myTransform = transform; hash = GameObject.Find("GM_Enemies").GetComponent<HashIDs>(); } void Start () { StartNavigating(); } void Update () { // checks if the target has arrived at its waypoint if (IsNavigating) { DistanceToMyWaypoint = nav.remainingDistance; DistanceToMyWaypointIsInfinity = System.Single.IsNaN (DistanceToMyWaypoint); if(!arrivedAtDestination ){ if (nav.remainingDistance < 0.01f && myWaypoint != null && !DistanceToMyWaypointIsInfinity && CanReachMyWaypoint){ Debug.Log ("I HAVE ARRIVED!"); arrivedAtWaypoint (); } } } if (IsAttacking && arrivedAtDestination) { Vector3 targetPostition = new Vector3( targetPlayer.position.x, this.transform.position.y, targetPlayer.position.z ) ; myTransform.LookAt(targetPostition); //myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(targetPlayer.position - myTransform.position), rotationSpeed * Time.deltaTime); EnemyGun.rotation = Quaternion.Slerp(EnemyGun.rotation, Quaternion.LookRotation(targetPlayer.position - EnemyGun.position), rotationSpeed * Time.deltaTime); } } public void setWaypoint(GameObject nextWaypoint) { myWaypoint = nextWaypoint.transform; } public void StartNavigating () { NavMeshPath path = new NavMeshPath(); bool hasFoundPath = nav.CalculatePath(myWaypoint.position, path); if(path.status == NavMeshPathStatus.PathComplete) { print("The agent can reach the destination"); CanReachMyWaypoint = true; if (targetPlayer != null) { nav.SetDestination (myWaypoint.position); //nav.destination = myWaypoint.position; } } else if(path.status == NavMeshPathStatus.PathPartial) { print("The agent can only get close to the destination"); CanReachMyWaypoint = false; if (targetPlayer != null) { nav.SetDestination (myWaypoint.position); //nav.destination = myWaypoint.position; } } else if(path.status == NavMeshPathStatus.PathInvalid) { print("The agent cannot reach the destination"); print("hasFoundPath will be false"); CanReachMyWaypoint = false; } } void arrivedAtWaypoint () { IsNavigating = false; arrivedAtDestination = true; nav.Stop(); nav.enabled = false; nav.updatePosition = false; nav.updateRotation = true; // animation IsAttacking = true; enemyFireScript.isAttacking = true; } }
Unfortunately, Unity's Nav Mesh Agent is a black box with few details exposed. My guess is that after calling SetDestintion on your nav agent, there is additional work that the nav mesh agent has to do later, probably in an internal Update() call. If your Update() is being called first, it may be that the remaining distance is 0 because the nag agent is still undergoing initialization. For example, I do know that one of the first things that happens to a Nav Mesh Agent on creation is that it gets snapped to the nav mesh. Perhaps this happens in an Update() call, before a path is finally applied. Try checking the following nav agent member variables - maybe one of them will have information about the state: pathPending isActiveAndEnabled isOnNavMesh You could also look at your own waypoint position and make sure the distance is *actually close to zero before stopping navigation. As an aside, note that you are actually computing the entire path twice, once using CalculatePath, and once using SetDestination. Instead, you can use SetPath() after CalculatePath() to avoid recomputing the path in the same function call.
Thank you very much for the answer (and so sorry for the late reply!)! That was very helpful and thanks for the tip on the double path calculation