Colliders or sqrMagnitude for triggering events

Hi friends,

I’ve got some questions for you, for more experienced of you using Unity:

For example if I got a lot of “enemies” in one scene let’s say hundreds (150-300), what is the best way to achieve best performance:

a) using sqrMagnitude distance between player & them for triggering events:
My example code:

public Tranform player;
private float distance;
private Quaternion quat180;

private void Awake(){
quat180 = Quaternion.Euler(0f, -180f, 0f);
}

void LateUpdate()
   {
            Action();
    }

    private void Action()
    {    
     
        if (player != null)    
        {
//CALCULATE THE DISTANCE BETWEEN PLAYER & ENEMY
        distance= (player.transform.position - transform.position).sqrMagnitude;

//ACTION
            if (distance < _attackDistance )
            {
                StartCoroutine(Attack(true));

                Debug.DrawLine(transform.position, player.transform.position, Color.red);
                Debug.Log("THE DISTANCE BETWEEN PLAYER & ENEMY: " + distance);
            }        
        }
        if (distance <= 40)
        {
            transform.rotation = Quaternion.Euler(0f, -180f, 0f);
        }
        else if (distance > _attackDistance)
        {        
            StartCoroutine(Attack(false));

            Debug.DrawLine(transform.position, player.transform.position, Color.green);
            Debug.Log("THE DISTANCE BETWEEN PLAYER & ENEMY: " + distance);
        }
    }

b) triggering events using colliders (in my case 2D Colliders) e.g:

void OnTriggerEnter2D(Collider2D o)
    {
        if(o.gameObject.tag == "Player")
        {
             StartCoroutine(Attack(true));
        }
    }

*P.S: I’m developing for mobile devices !

Any advice & feedback will be much appreciated, thanks in advance ! :wink:

1 Like

Your player could have trigger collider instead of enemies. That would save a lot of time and performance.

1 Like

In this case I think triggering using colliders wouldve been much more efficient. The code is more short and when searching for tags the system does not need a lot of power, in fact there is almost no loose in game fps :slight_smile:

1 Like

Hm. I would bet on the distance checking approach (with all colliders removed of course). I guess this depends also on the type of you colliders.

Plus there are several optimization options in your distance checking code. You don’t have to call Quaterion.Euler every time. Just store the quaterion locally. Don’t create tempDist on every call. Use a global tempDist variable. Move all checks into the if (player != null) statement. Cache player.transform instead of player. And so on.

Plus you could restrict the checks at all. Don’t check if the player/enemy hasn’t moved. Or move the distance check part from each enemy gameobject to a central manager component to do checks for all enemies, which would provide some more optimization option.

1 Like

Thanks all of you for sharing your experience,

@Duugu what you mean by storing the quaterion locally and cache the player.transform? And if I use a global tempDist how then can I update the distance from the player and enemies ? Thanks !

The quaternion doesn’t change. So there’s no need to calculate it again and again via Quaternion.Euler.

private Quaternion quat180;

private void Start(){
quat180 = Quaternion.Euler(0f, -180f, 0f);
}

private void Action(){
//stuff
        if (distance <= 40)
        {
            transform.rotation = quat180;
        }
}

As you’re using player.transform.position I guess you’re caching the player gameobject somewhere.
Like this:

private Gameobject player;
private void Start(){
player  = //get a reference to the player gameobject;
}

Or player is public and you’re assigning the player gameobject via the inspector.

Using the player gameobject Unity has to access the transform component via player on each call. So, why not caching the transform component instead of the player gameobject?
Then instead of
player.transform.position
use
playerTransform.position

(see code below)

Just declare the variable outside of you LateUpdate Funktion.

private Gameobject player;
private Tranform playerTransform;
private float tmpDist;
private void Start(){
player  = //get a reference to the player gameobject;
playerTransform = player.transform;
}
private void LateUpdate(){
tempDist = ....;
}

[e]
Please keep in mind, that, depending on the number of objects and lots of other stuff the performance gain of all this may be marginal. But as you explicit asked for optimization … :slight_smile:

Thanks a lot @Duugu , I will give’it a try, also I modified/updated the code from the first post :wink:

Profiler.

With a high number of enemies, the physics engine might actually win. The physics engine has some optimisations that mean it does no where near as many distance checks.

So if you had 300 objects that’s roughly 90000 distance checks per frame to check for all interactions. The physics engine will do far less then this due to how the data is structured.

1 Like