AI and Enemy Detection

Hi All,

I am trying to figure out the most efficient(performance conscience) way to detect ‘enemy’ at long range(100-300 unit distance) AND short range(10 unit distance). This is for a game with about 100 units+ on each side.

Here’s what I have contemplated so far:

  1. Use cast raycast sphere and filter units using tags
  2. Use a really large collider(trigger) and filter units using tags
  3. Keep a database of all Enemy/Friendly units on the map and update them every X seconds -this will require a lot of loops to for each unit to search through and find the nearest enemy.

I am assuming #3 would be the most performance costing.

Is there anything wrong with, in a professional game dev. point of view, using #2, having a huge collider(with a layer assigned and tagged)?

I would really appreciate any wisdom you can give me on this matter.

Thank you!

I was building a game and had hit a very similar point as you. I had many enemies, and they all had a range of about 50 m to shoot lasers (60 m awareness). Due to a steering behaviours plugin I was using at the time, they had small sensors (colliders as triggers) about 5 m radius to detect nearby units. They also had much larger sensors (radius = awareness) to detect enemies at far range. This is an analog to implementation (2) that you listed above. Though it sounds cheap (CPU-wise), I actually ran into TONS of trouble performance-wise due to this. I’ll try to give a bit more detail:

The game would operate fine while I was playing. But then, once enemies and player-units began interacting, I would watch FPS dip to 15 during more hectic fights (maybe 20 v 20… big, but not the big-scale I wanted). It was VR (oculus) so this hit was HUGELY noticable. I was distraught so I checked out the profiler, and found out I was taking a HUGE hit (~20 ms) from something called PhysX.Sc::Scene::postIslandGen

The best advice I found was actually the bottom-listed comment here. Simply, it stated that large moving colliders push postIslandGen to the limit, especially when many many objects are moving in and out of it, and many of these huge colliders are movng around at once.

I was able to fix my problem and push FPS back to 60-70 range. The solution I implemented was actually close to your (3). Though it sounds processor intensive, it can be implemented in a smart way. I build an ObjectPool in nearly every game I make now, and just followed the basic Unity tutorial on Object Pooling here: https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/object-pooling

So, I now have a gameObject that tracks all my units (and lasers, and particle FX… everything really) and disables/enables them when they’re needed. This already improved my FPS as the myriad of particle FX were now pooled. Next, I eliminated the large colliders, and wrote a couple helper functions in the object pool that would

  • scroll through units in the pool, check to see if they’re active
  • if active, check to see if the (distance.sqrMagnitude < (awarenessRange*awarenessRange)
    [sqrMagnitude is less CPU intensive than .magnitude; important if called often]
  • if this is true, add gameObject to a list
  • cycle through list to find closest gameobject
  • return this gameobject

Though it sounds intensive, remember that background physics engines have to perform similar computations (not exactly the same, see this link) when we use colliders to detect units; they just do it in the background, so we are unaware of it. The list of units doesnt need to be updated every
frame because you are holding references to the units themselves. You simply scroll through them.

One thing I canNOT tell you is if (1) will be more efficient that (3). You may have to test this yourself. I am not sure if it is more efficient to scroll through a list of units and find the relevant ones, or shoot out a spherecast (As I said earlier, physics engines will have to perform similar checks on colliders).

However, based on my experience, I will tell you to avoid implementation (2). Though it seems simple (stick a sphere collider and perform actions in OnTrigger____!), there is a lot going on behind the scenes that could potentially devastate your performance. Maybe you can properly layer them so that it is less intensive, but I could not reach desired performance specs using this approach. This is my humble perspective.