Find a Target
Lesson 8 of 25 in Coddy's Unity Game: Tower Defense course.
A tower shoots the enemy nearest to it, as long as that enemy is within the tower's range. To choose, the tower needs every enemy on the board. FindObjectsByType<Enemy> would search the whole scene every frame for every tower, so instead the enemies keep a list of themselves: a static list on the Enemy class, which each enemy joins in OnEnable and leaves in OnDisable. Unity calls OnDisable on an object that is being destroyed, so a dead enemy leaves the list too. Pickups in a game can do the same:
public class Pickup : MonoBehaviour
{
public static readonly List<Pickup> All = new List<Pickup>();
void OnEnable()
{
All.Add(this);
}
void OnDisable()
{
All.Remove(this);
}
}Finding the nearest is a loop that remembers the best so far. A magnet that pulls the nearest pickup within pullRange starts with no pickup and with the range as the best distance, so a pickup further away can never win:
Pickup best = null;
float bestDistance = pullRange;
foreach (Pickup pickup in Pickup.All)
{
// closer than the best so far? keep it, and its distance
}Vector3.Distance(a, b) gives the distance between two points. When nothing is within range, the loop keeps nothing, and the answer is null.Challenge
MediumEach tower picks the nearest enemy in range.
- In
Enemy, addpublic static readonly List<Enemy> All = new List<Enemy>();; addthisinOnEnable, remove it inOnDisable. - In
Tower, addpublic float range = 4f;andprivate Enemy target;. - Every frame, find the nearest enemy in
Enemy.Allwithinrange(or null), log"Target: " + found.namewhen it is new, and keep it intarget.
Press Play and build by the path: the Console names each new target. Then Check.
Try it yourself
using UnityEngine;
// Comes later: a tower finds an enemy in range, turns to it and fires.
public class Tower : MonoBehaviour
{
}
All lessons in Unity Game: Tower Defense
Practice on your own: Unity playground