I am making a tower defense game where NavMeshAgents travel through a path from the spawn point to the end. My enemies all travel the same path (for now), but they travel at different speeds. Currently, my towers always target the enemy closest to them. I want my towers to target the enemy that needs to travel the least distance along the path to get to the end.
I tried using agent.remainingDistance but it keeps returning Infinity (and according to the documentation, that means the agent doesn't know the remaining distance).
Tower.cs:
public Transform target;
// a lot of other stuff
void UpdateTarget()
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag(Tags.enemyTag);
float shortestDistance = Mathf.Infinity;
GameObject targetEnemy = null;
foreach (GameObject enemy in enemies)
{
float distance = enemy.GetComponent<Enemy>().agent.remainingDistance;
if (distance < shortestDistance && Vector3.Distance(transform.position, enemy.transform.position) <= range * 10 + rangeBuff)
{
shortestDistance = distance;
targetEnemy = enemy;
}
}
if (targetEnemy != null)
{
target = targetEnemy.transform;
}
else
{
target = null;
}
}
// a lot of other stuff
Enemy.cs:
public class Enemy : MonoBehaviour, IPooledObject
{
public EnemySplit[] splits;
public bool cameFromSplit = false;
public EnemyBlueprint enemy;
public float health;
public float speed;
[HideInInspector]
public float slow;
public Image healthBar;
public List<Tower> towersSlowing = new List<Tower>();
[HideInInspector]
public NavMeshAgent agent;
private GameObject end;
public bool stunned;
void Awake()
{
agent = GetComponent<NavMeshAgent>();
end = GameObject.FindGameObjectWithTag(Tags.endTag);
}
public void OnSpawned()
{
slow = 1f;
speed = enemy.startSpeed;
health = enemy.startHealth;
splits = enemy.splits;
agent.speed = speed * 10;
agent.updateUpAxis = false;
agent.updateRotation = false;
agent.SetDestination(end.transform.position);
if (cameFromSplit)
{
StartCoroutine(CameFromSplit());
}
foreach (EnemyReinforcements re in enemy.reinforcements)
{
StartCoroutine(HandleReinforcement(re.enemyIndex, re.rate, re.count));
}
InvokeRepeating("UpdateHealth", 0f, 0.1f);
InvokeRepeating("UpdateCheck", 0f, 0.2f);
//StartCoroutine(LateStart());
transform.rotation = Quaternion.Euler(90, 0, 0);
}
// a lot of other stuff
I'm using object pooling to summon my enemies. So treat OnSpawned() as Start().
UPDATE: Changed my targeting code to
if (enemy.GetComponent<Enemy>().agent.pathPending) distance = Vector3.Distance(enemy.transform.position, transform.position);
else { distance = enemy.GetComponent<Enemy>().agent.remainingDistance; }
and it seems to be targeting the closest enemy. So, the enemies are still pathPending...??