- Home /
Advice on enemy detection and sorting.
Hi. My game will have dozens of 'agents' running around a level, each with their own stats which will affect their behaviour with one another. Because of this I need a setup which will let me achieve several things.
Let's take one agent for example. He needs to know how many hostiles are in his vicinity at any time. He needs to know which is the closest so that he can prioritize targets or decide to run away.
Initially I had thought to add a cylinder to the agent and use is as a radius, like an area of awareness. The collider would pick up anyone entering into it and add them to a list on the agent's script. It would ideally also cast a ray to each enemy every frame and come back with the distance. This would make sure that the agent was always reacting to the closest threat (in case enemy 1 is suddenly overtaken by a faster enemy2 and thus is the new closest enemy). If there are no enemies within the radius, the list is empty.
Is this a viable idea? I've not used lists before but I read that they were superior to arrays. Is it okay to have multiple agents casting (potentially) multiple rays every frame so that they all know which enemies are closest? OR would this cripple the framerate (It's to go on web browser).
I would appreciate any thoughts on how anyone would do this differently :)
Answer by Jamora · Aug 09, 2013 at 07:00 PM
You should try to minimize the amount of raycasts to improve performance. Or at least use physics layers so there is as few colliders for each ray to check as possible.
Arrays are the closest to direct memory access in C# that I know of; Lists offer conveniance methods to manage an array easily (resizing etc.). So arrays are more performant than Lists, but the difference really is negligible. Unless you're talking of the UnityScript Array which has really poor performance (and is a list itself)...
Now to your actual question... You should store each enemy gameobject in a list somewhere (an enemyManager class?) as well as the player's GameObject. Then determining the closest enemy is a matter of sorting the list of enemies by distance to the player. You could also determine the enemies in teh vicinity by choosing a cutoff point for the distance.
If you're really concerned of performance, you don't even need the actual distance, but the square of the distance (because the distance is calculated from the pythagorean theorem). Square root calculations are expensive computationally. The choice of the sorting algorithm is siqnificant as well: the best comparison sorts (e.g. merge sort) run in the worst case O(n log(n)) time, while the comparison sort a normal person to use to sort a deck of cards(insertion sort) is O(n^2). In concrete terms; if you have a list with a million elements, merge sort would take almost 1.4*10^7 million time units, and insertion sort 10^12 time units. That's a difference of 5 zeros at the end of the number.
Thanks for the reply. Very in-depth and slightly over my head with the mathematics! The idea of storing all of the enemies in one list (if I'm taking your explanation as you meant it) and comparing the players' distance to it would be a good idea IF I was to have just one player character. This is more of a strategy game however and there will hopefully be between 1-50 (or more) agents per side, each one needing to know the distance to everyone else and I would imagine that constantly checking distance every frame for all of them would be bad. Hence the radius which will trigger a distance check.
I did however use your advice for layer exclusion and you've given me some stuff to think about :)
Your answer
Follow this Question
Related Questions
Create game objects with unique IDs and detect them? 1 Answer
List.Add(waypoints) broken? What am I missing? 2 Answers
How to prioritise detection of Button click in RTS building placement using raycast 1 Answer
Unity Rotate Raycast on Quaternion 1 Answer
Why doesn't Physics.Raycast(ray, RaycastHit, distance) work? 1 Answer