Finding Closest Object with considering the Performance

Hey Guys,
Does anyone have an idea how i could find the closest enemy object without ruining the performance by calling it every single frame ?

There are probably thousands of ways (maybe use multiple ray casts? ) but which is the best when it comes to performance ??

Thank you for any help and good night (3:30 am in German time)

Good question.
For my projects, I do something by the lines of this;

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    public Transform target;
    public float closeDistance = 25.0F;
    void Update() {
        if (target) {
            Vector3 offset = target.position - transform.position;
            float sqrLen = offset.sqrMagnitude;
            if (sqrLen < closeDistance)
                //If the [target] is closer than [closeDistance] away from me,
                //execute code here.
            
        }
    }
}

Make sure closeDistance is the squared amount of the distance you want. Usually, the magnitude script performs the sqrt function which is quite memory expensive, so sqrMagnitude is a faster alternative. I’m sure computers can do maths without eating your memory away unlike calculating multiple raycasts on a 3D or 2D space. Hopefully, that helps :wink:

Hey I had a similar situation earlier today. I was able to solve it by using Physics.OverlapSphere. This allows you to detect objects around you 360 degrees. If you don’t want to call this method every frame, you can call it in a coroutine instead of update. Here is a code example.

using UnityEngine;
using System.Collections;

public class Raycast_ToJump : MonoBehaviour {
                
                
                float distanceToCheckForEnemy = 1;
                	
                // Update is called once per frame
                void Update () {
                	DetectEnemy(transform.position, 1);
                
                }
                
                private void DetectEnemy(Vector3 center, float radius) {
                	var hitColliders = Physics.OverlapSphere(center, radius);
                
                	for (var i = 0; i < hitColliders.Length; i++) {
                		// collect information on the hits here
                		print(hitColliders*.tag);*

}
}
}

Here is an optimized solution that allows you to set how often to run a check “findDelay”.
I’m using the optimized Vector3.SqrMagnitude instead of Vector3.Distance because we only need to know which enemy is closest, not the exact meter distance (which would need Square-Root).
The list of enemies is stored at start so you may need to update the list if an enemy is added or removed.
Attach on any GameObject in scene, and from any script:
EnemyFinder.closestEnemy
to access current closest enemy.
Hope it helps! :slight_smile:

using UnityEngine;
using System.Collections;

public class EnemyFinder : MonoBehaviour {

	public float findDelay=0.25f;//updates 4 times per second
	public static GameObject closestEnemy;

	GameObject[] enemies;

	void Start () {
		enemies=GameObject.FindGameObjectsWithTag("Enemy");

		InvokeRepeating("findClosestEnemy",0f,findDelay);
	}
	
	public void findClosestEnemy(){
		float smallestDist=float.MaxValue;
		Vector3 playerPos=Camera.main.transform.position; // assuming player is in same position as main camera
		GameObject newClosestEnemy=closestEnemy;

		foreach(GameObject enemyObj in enemies){
			float dist=Vector3.SqrMagnitude(enemyObj.transform.position-playerPos);
			if(dist<smallestDist){
				newClosestEnemy=enemyObj;
				smallestDist=dist;
			}
		}

		if(newClosestEnemy!=closestEnemy){
			closestEnemy=newClosestEnemy;
			print("NEW Closest Enemy = "+closestEnemy);
		}
	}
}

Thanks for the tips !