I am making a tower defense game. in short, my towers current targeting system make it so that they target the closest enemy to themselves. i am trying to make a targeting system that sets the towers target to the enemy furthest on the track. i currently have a progress variable that tracks their progress on the track by multiplying their time alive by their speed. because i have different types of enemies, this task proves difficult to me and was wondering if anybody could help me
void UpdateTarget()
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
float shortestDistance = Mathf.Infinity;
GameObject nearestEnemy = null;
foreach (GameObject enemy in enemies)
{
float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
if (distanceToEnemy < shortestDistance)
{
shortestDistance = distanceToEnemy;
nearestEnemy = enemy;
}
}
if (nearestEnemy != null && shortestDistance <= range)
{
target = nearestEnemy.transform;
}
else
{
target = null;
}
}
let me know if you need any more information about the code for example the progress variable
Create a base enemy class that has functions and attributes that will all enemies will have.
public abstract class Enemy : MonoBehaviour {
public float health;
public float timeAlive;
public float speed;
public Enemy (){
timeAlive = 0;
}
/// <summary>
/// Call this in FixedUpdate
/// </summary>
void OnTick () =>
timeAlive += Time.deltaTime;
/// <summary>
/// Calculates the target priority for a certai nenemy
/// </summary>
public abstract float GetTargetPriority ();
}
Below we will use custom enemy classes derived from the base evenmy class. Attach them to your enemies (1 per enemy)
You can create as many of your own as you like, below i created an enemy that has armor and one that keeps ketting faster and faster.
Note they derive from the Enemy abstract class. You can customize their behaviour this way and add write custom priority functions to suite your needs.
public class SpeedIncreasingEnemy : Enemy {
void FixedUpdate () {
// Do the on tick function
OnTick();
// Increase speed slightly every tick
speed += Time.deltaTime / 2;
}
public float GetTargetPriority () {
return timeAlive * speed + health;
}
}
public class ArmoredEnemy : Enemy {
public float armor;
void FixedUpdate () => OnTick();
public float GetTargetPriority () {
return timeAlive * speed + health + armor;
}
}
... Create your own custom classes
Now we can easily select target priority through your script. I made small changes that should work
void UpdateTarget()
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
GameObject nearestEnemy = enemies.FirstOrDefault(); // using System.Linq;
foreach (GameObject enemy in enemies)
{
if (nearestEnemy == enemy)
continue;
if (nearestEnemy.GetComponent<Enemy>().GetTargetPriority() < enemy.GetComponent<Enemy>().GetTargetPriority())
nearestEnemy = enemy;
}
// This code is fine
if (nearestEnemy != null && shortestDistance <= range)
{
target = nearestEnemy.transform;
}
else
{
target = null;
}
}