Hello,
So as the title suggests, I’m looking for a way to find the nearest object with a certain component that causes the least lag. Using OverlapSphere causes too much lag if there’s too many game objects nearby, and this is due to the fact that I use tiny cubes with colliders as blood. (9 in total).
Is there perhaps a better way to fix this lag problem I’m having?
Code for Detection:
public void senseEnemiesNearby(float radius){
if (target == null) {
Collider[] hitColliders = Physics.OverlapSphere(transform.position, radius);
senseEnemies = true;
savedLoc = loc;
Cube cub = GetClosestEnemy (hitColliders, radius);
if (cub != null) {
if (cub.team != team) {
setTarget (cub);
}
}
}
}
private Cube GetClosestEnemy(Collider[] enemies, float radius)
{
Cube cub = null;
float minDist = radius;
Vector3 currentPos = transform.position;
foreach (Collider c in enemies)
{
if (c.gameObject != gameObject) {
if (c.gameObject.GetComponent<Cube> () != null && c.gameObject.GetComponent<Cube> ().team != team) {
Transform t = c.transform;
float dist = Vector3.Distance(t.position, currentPos);
if (dist < minDist)
{
cub = c.gameObject.GetComponent<Cube> ();
minDist = dist;
}
}
}
}
return cub;
}
Thanks
HighlordWeaponry
Here are three general performance boosters to your algorithm:
- First of all you may want to use layers. OverlapSphere has an additional layermask parameter.
- Next you shouldn’t use GetComponent more than once per object. Currently you use GetComponent up to 3 times per object. Just create a local variable inside the foreach loop and get the component once.
- Finally when sorting objects based on the distance it’s faster to compare sqrMagnitude. It of course doesn’t tell your the actual distance but the greater than / lower than relation will stay the same.
So do something like this:
public LayerMask layers;
public void senseEnemiesNearby(float radius)
{
if (target == null)
{
Collider[] hitColliders = Physics.OverlapSphere(transform.position, radius, layers);
senseEnemies = true;
savedLoc = loc;
Cube cub = GetClosestEnemy (hitColliders, radius);
if (cub != null)
{
setTarget (cub);
}
}
}
private Cube GetClosestEnemy(Collider[] enemies, float radius)
{
Cube cub = null;
float minDist = radius;
Vector3 currentPos = transform.position;
foreach (Collider c in enemies)
{
if (c.gameObject == gameObject)
continue;
Cube cube = c.GetComponent<Cube>();
if (cube != null && cube.team != team)
{
Transform t = c.transform.position - currentPos;
float dist = t.x*t.x + t.y*t.y + t.z*t.z; // Same as "= t.sqrMagnitude;" but faster
if (dist < minDist)
{
cub = cube;
minDist = dist;
}
}
}
return cub;
}
Note i removed your second team check in your “senseEnemiesNearby” method. Since your “GetClosestEnemy” method can only return an object that has to be on a different team the null check is enough.
How many objects are there in total and how many are usually in range of the OverlapSphere? I doubt that this actually caused much slowdown. Have you used the Profiler to narrow down your bottleneck?