Finding a gameobject with a specific tag within a given distance

This little bit of code is causing very bad performance when I have lots of gameobjects tagged as “Enemy” with the script that the follow code is from attached:

GameObject[] Zombies = GameObject.FindGameObjectsWithTag("Enemy");
        foreach(GameObject ZombieObj in Zombies)
        {
            Vector3 DirectionToZombie = ZombieObj.transform.position - transform.position;
            float DistanceToZombie = DirectionToZombie.magnitude;
            Zombie Zombie = ZombieObj.GetComponent<Zombie>();
            if(DistanceToZombie < ZombieRecruitmentRange && Zombie.IsHostile == true && Zombie.CanRecruit == true && DistanceToTarget < ZombiesStopRecruitingDistance)
            {
                IsHostile = true;
                HostileTimer = HostileCoolTime;
            }
        }

I am trying to find if a nearby zombie is hostile and within range to make an unhostile zombie turn hostile. Currently with this code I am checking every single zombie gameobject in the game tagged “enemy” and then checking if it is within range to make it hostile. This is causing bad performance because every single zombie is checking for every single other zombie, causing exponential performance loss. However I don’t know another way to get the same functionality with better performance. I think I need to check if there is a gameobject tagged “Enemy” in range first, instead of checking every gameobject and then checking if it is in range, but I don’t know how to do this in code.

If they have colliders:

Collider[] hits = Physics.OverlapSphere(position, radius);
foreach (Collider hit in hits)
{
  // if (hit.gameObject. ...
}
1 Like

When and where are you running this piece of code specifically?
You mention enemies also checking for enemies, and the code has a “ZombieRecruitmentRange”, so I’m guessing there is some form of enemy rallying other enemies?
Are you running this in Update?

This looks like a classic case of having too much functionality in one place. If I had to do something distance related, step 1 would be to have collision take care of involved parties at any given time.

Say in a zombie game, the player has a sphere collider which involves zombies in it to activate code to notice the player. Or even better, an invisible collider spawns only when the player screws up, never needing a moment by moment checking. For zombies rallying more zombies, an alerted zombie then spawns an invisible collider that alerts zombies within it if there are, after which the invisible collider is destroyed. This way only objects nearby each other interact with each other, the code is segmented between smaller scripts on the player/enemy/invisible-collider, and none of it needs to run on update.

If you get familiar with Physics, you wont even need invisible colliders, you can just check overlaps.

Thanks

1 Like