1
\$\begingroup\$

If the player fires his firearm within a certain hearing range of an Enemy Bot, the Enemy AI should be alerted to his position. My initial solution to the problem was the following: Everytime the player fires a shot, find all Enemy AI Game Objects and trigger a function that checks wether the player is within hearing range or not.

The problem is some weapons have a firerate of up to 20 shots per second. And if there are 25 enemies in the scene it means that, while shooting, I will be asking for GameObject.FindGameObjectsWithTag(Enemy); and accessing a function within 500 times every second. This is not very performance friendly.

I cannot think of a better way to do this. Is there?

\$\endgroup\$
  • \$\begingroup\$ Don't know how performed it is by why not use a sphere collider that grows real quick and only restart the process at a certain interval? \$\endgroup\$ – Sidar Sep 14 '17 at 13:54
  • 1
    \$\begingroup\$ @Sidar scaling colliders is usually not a very fast operation inside a physics engine, so there will very likely be more efficient solutions in most cases. \$\endgroup\$ – DMGregory Sep 14 '17 at 15:24
  • \$\begingroup\$ I've known about that, but I don't know the scale of his game though. \$\endgroup\$ – Sidar Sep 14 '17 at 16:38
4
\$\begingroup\$

This assumes that you're not worried about audio occlusion (sound muffling around obstacles like walls etc.).

I would have a circular/spherical trigger collider (SoundCollider) attached to your gun/weapon that is the size / radius of how far you want the sound to travel. When you shoot: it that turns on this SoundCollider. Enemies can have an appropriate Rigidbody (Listener) to collide with the trigger and a handler in a component that handles what to do if they are triggered if they are in range of your SoundCollider.

Couple of Pros I can see to this approach:

  • You can have an easy to edit variable that changes the radius of the SoundCollider, making some weapons quieter than others.
  • You can let Unity handle the events between your Gun sound and the enemies in hearing range.
  • Effects can be applied to the collider if necessary so when it is active a radar on the mini-map (if you need one) can show the area that sound will travel to.
  • As you only need to turn the SoundCollider on or off instead of sending multiple events, it will work regardless of firerate on your weapons as you simply turn it on when you start firing and have a small delay to turn it off once you've stopped.
  • You only need Listeners on appropriate enemies and you don't need to use Tags to filter through them. Disabling a Listener can make a unit "deaf" quite easily if you need them to not hear anything under certain conditions (interactive cut-scene).

It's a concept but can work well, I used something similar to make an AOE damage ability on a unit but the concept is essentially the same - Unit in certain proximity triggers code when ability is active (gun is firing).

\$\endgroup\$
2
\$\begingroup\$

This is a good place for events. Both c# and unity have an event system, so use whichever you're more comfortable with.

With events, you don't have to "find" the game objects. The event can pass whatever necessary information, and each AI determines if they can hear it.

Because events work as a "subscription" system, it's fairly easy to "deafen" an ai based on scripted events, distance from player, loading areas, etc.

docs for unityEvent: https://docs.unity3d.com/ScriptReference/Events.UnityEvent.html

docs for c# event: https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx

\$\endgroup\$
2
\$\begingroup\$
  1. Does every shot need to be heard individually, or just the first in a volley / every 50th in a sustained spray?

  2. Do your enemies change so drastically frame to frame that you need to search every gameobject in the whole scene to see if it now has an enemy tag?

    • Instead, could your enemies register themselves to a master list on spawn, and un-register themselves when killed/despawned? Then you only need to search the enemy list.

      (This is effectively how an Event solution as Zebraman suggests works under the hood - enemies subscribe to the noise event on spawn, adding themselves to a master list of event subscribers)

    • Better yet, could this master list be a spatial partition your enemies update when they move? Then you only need to search the portions of the partition within hearing range. (Probably only helpful if you have hundreds of enemies — for dozens, a linear scan through the list is reasonable and much simpler)

  3. If all or most of your range queries are centered on the player, could you use a physics trigger collider surrounding your player to capture and maintain a list of only those enemies within perception range, then process only that list?

\$\endgroup\$
1
\$\begingroup\$

Perhaps you could make use of influence maps?

Every time you shoot you can propagate values trough the influence map and make AI aware.

Obviously it adds more complexity.

\$\endgroup\$
0
\$\begingroup\$

I simplified things even more than the other answers suggest so I thought I'd contribute:

  1. A sphere collider representing sound travel distance around the player updates once a second: If the weapon has been fired in that second it turns itself on for one second and it is disabled by default.
  2. Everytime an enemy bot collides with that Sound collider a timer is set to 30s and the bot is set to alert and does his thing.
  3. If that timer runs out and the bot hasn't heard or seen anything it will go back to doing whatever it did before.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.