Getting Enemies to Switch Targets

Hello,

I’m new to Unity and I’m working on a game where bomb enemies spawn from empty game objects and immediately start walking towards a tower. Once they collide with the tower, the tower takes 1 damage and the enemy object is destroyed.

My problem is that I have four towers in the scene, and I’m trying to get the bomb enemies to switch targets to a different tower if the first one is destroyed. Currently they just keep spawning and walking to the location where the tower used to be. Here’s one of my attempts just trying to get them to switch targets at least once:

public class FollowAI : MonoBehaviour
{
    public Transform target;
    public Transform altTarget1;
    public Transform altTarget2;
    public Transform altTarget3;
    public Transform altTarget4;
    public Transform myTransform;
    public float speed = 3;

    void Update()
    {
        SwitchTarget();
        transform.LookAt(target);
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }

    void SwitchTarget()
    {
        if (target != null)
        {
            target = altTarget1;
        }
    }
}

In the Inspector, I assigned prefabs for each tower and finally the player character to altTarget1 - altTarget4. After reading a bit, I found out that checking if a destroyed object is null doesn’t really work; although when I tried using “if (target != null && !target.Equals(null)),” which I found suggested online, the enemies did switch to the target I placed in altTarget1 in the Inspector, but it switched immediately without destroying the original target first.

Another option I thought I could try would be to check if the tower’s health is equal to zero instead of checking if it is null. The problem is that I’m not sure how to access the currentHealth property of the tower, since it’s in a script attached to the tower object.

I was wondering if part of the problem is also that I am setting these transform settings in prefab objects, which means I am not able to drag the actual scene objects into those properties. I can only drag the prefab versions of the towers to the FollowAI script attached to the prefab bomb enemy.

Maybe there’s a simple solution I just can’t see because I’m so inexperienced, but if anyone could help me solve this problem, I would really appreciate it!

That’s incorrect. That’s the best way to check if a GameObject is destroyed.

That’s your actual issue. The Prefab and the instanced Clone aren’t the same object, so your Prefab isn’t being destroyed and will never be null.

At runtime, try using GameObject.FindObjectsOfType to create an array of your available towers and use that as your list of targets instead. Something like this:

public float speed = 3;

private GameObject[] targets;
private Transform target;

void Update()
{
   SwitchTarget();

   if(target == null)
       return;
       
   transform.LookAt(target);
   transform.Translate(Vector3.forward * speed * Time.deltaTime);
}

void SwitchTarget()
{
   // if our list of targets is empty, find them
   if(targets == null)
       targets = GameObject.FindObjectsOfType<Tower>();

   // loop through the list of targets and select the next one that's alive
   for(int i = 0; i < targets.Length; ++i)
   {
       if(targets[i] != null)
       {
           target = targets[i];

           return;
       }
   }
}

This code assumes you have a script named Tower attached to each tower object for it to find. You may want to use other ways to id them, like tags, if you don’t have special scripts on each tower. Once you’re comfortable with finding GameObjects at runtime like this, you can expand the AI logic to chase after the closest tower for example, instead of just any order.

And Grozz wrote this:

It is totally true what Grozz wrote, BUT! There is a very important catch:

If you Destroy() something right now, then immediately check if (something), the thing will appear to have NOT been destroyed.

This is because Destroy() doesn’t fully happen until end of frame. The object is doomed but it will still show up as not doomed.

The next and subsequent frames it WILL appear destroyed.

The best way to Destroy() something is to both Destroy() it AND set the variable it was stored in to null.

1 Like

Thank you for your response. This is very helpful even beyond my original question. I am working on a different project for the next day or so, but I will definitely try this out and play around with finding objects at runtime. Yay, learning!

2 Likes