How many colliders is too many?

Our game has perhaps 100 sphere colliders set as triggers in order to activate certain things. The scripts that use these triggers check at OnCollisionEnter whether the collider is the player. The whole scene has about 1000 other (non-trigger) colliders. How much overhead would we be saving by going through and replacing all the sphere trigger systems with:

var distance = 20;
var player : Transform;

Update() {
	if (Vector3.Distance(player, transform.position) < distance)
		//do whatever
}

I’m asking because removing the colliders from 100 sphere colliders and copying their radii into the inspector would be a pain, and I don’t want to do it if the performance gain would be minimal.

Im not sure about this so take my comment as just a comment.

I think an sphere collider just do that, check for a distance, but in a FixedUpdate based interval, so if you do that on an Update, you will be gaining calculations depending on how slow the FPS are.

Other way to check triggers is just checking for them every 1 or 2 seconds since the player move slowly and probably, if he enters a trigger, he will take more than a seconds to exit, right?.

Here are some tips.

  • Name your triggers like TriggerN: Trigger1, Trigger2, …, TriggerN
  • Check for distance once a second or two and update the snapshot of the states of the triggers
  • Check the snapshot for better performance
var mPlayer : Transform;
var mDistance = 10.0; // Distance to trigger

private static var N = 1; // Total triggers
private var mState = new boolean [N]; // Actual state of the triggers

function Awake ()
{
	var trigger = "";
	
	for ( i = 0; i < N; i++ )
		mState [i] = false;
	
	while ( true )
	{
		for ( i = 1; i <= N; i++ )
		{	
			trigger = "Trigger" + i;
		
			if ( Vector3.Distance (mPlayer.position, GameObject.Find (trigger).transform.position) < mDistance )
			{
				mState [i] = true;
			}
			else
			{
				mState [i] = false;
			}
		}
		
		yield WaitForSeconds (2); // Wait to update the triggers again
	}
}


function GetState (pTrigger : int) : boolean
{
	pTrigger -= 1;
	
	if ( pTrigger < 0 || pTrigger >= N )
		return false;

	return mState [pTrigger];
}

Untested!

.ORG

That solution would be really…really…slow. And kind of pointless…

I don’t think that having 100 trigger colliders would be a big drain, but it does depend on how many other colliders are in the scene. If the player is the only collider, the collider system will be much faster. If you’ve got falling rocks and enemies all over the place, then a trigger collider would be checking all of those as well and it might be faster to check only the player.

You mean my solution ? If so… can you explain why ? it’s seems very logical to me

Anyways… i would stick to the colliders though

.ORG

We have about 1000 other colliders in the scene.

GameObject.Find() is a very expensive operation, as it essentially needs to search though all GameObjects (Actually Vector3.Distance is itself a bit iffy, it shouldn’t be used for going through large amounts of objects each frame).
Collision spheres, on the other hand, are handled by Novodex, which does a lot of intelligent partitioning of colliders so it doesn’t need to check everything against everything else.
In general if you can use the Physics engine for something then do it. It’s insanely fast. Your code is probably (with all respect :smile:) a factor 10000-100000 slower, even-though you only check each object every 2 sec;

1000 colluders in themselves are not a problem.

You can automatically separate colliders and objects in groups, with a master object that acquire nearest colliders in “start” function and activate/deactivate them if the player is in range.

But if there is real a problem then save the GameObjects of the triggers in a array too in an Awake function… i just gave the fastest solution, not the optimal, that’s up to you, the programmer, i usually give only ideas and tips.

Want a more optimal solution? have an index and check for the distance to that index trigger adding 1 every time and cycling accordingly, so you check 1 distance 1 time in an Update or FixedUpdate basis.

Any suggestions and comments are well received though.

.ORG

I’d like to second this. Think it’s normally called “bucket collisions”. The idea is to programatically divide the objects into a grid (or groups), and then just check against the relevant ones. You can use this for non-static objects as well, by simply reassigning them when they move from one “bucket area” to another.

Way back when this used to be a critical technique when dealing with large number of objects interacting, so I’d guess that applying this within Unity would allow you to have an insane ammount of colliders. :wink:

Good luck!

1 Like