- Home /
How to optimize hundreds of sphere colliders
Hi,
I realize that this is quite ambitious, but I should explain my reasoning why. The game I am creating spawns hundreds of friendly fighters ships, each of which have an enemy detector. This detector is basically an invisible sphere collider that "sees" if any enemy is too close; if so, it chases it.
Originally, friendly ships hit each others' detector, causing performance issues. So I decided to make them ignore each others' detectors by using layers and performance improved. I can make about 400 or so ships now before things really slow down. Without the enemy detector colliders performance is even better -- but those detectors are necessary.
Any thoughts? I suppose I should probably use some kind of grid, kdtree, or data structure to somehow help performance, although I'm not sure where to start. I'm also not sure if unity's internal engine helps in this regard.
Thank you
PhysX already uses performance optimizations, so at some point you just need to limit the number of objects you're using. CPU power is finite and can only do so much.
I feel like there is a way around this. I.e. if there are no enemies your part of the map, disable the detector. The problem is that lots of Unity stuff is abstracted away, so I would have to make intelligent use of its resources.
Answer by Statement · Aug 13, 2011 at 07:50 PM
Do you have any rigid body on them? If you use any collider without a rigid body, and move them, physx will bake the static collision data causing performance hits. If you haven't got rigid bodies on them, just slap them on and set isKinematic to true and you should see some improvement.
Another thing you could try is to perform a Physics.OverlapSphere every 0.1 seconds for detection purposes, but that would also require a collider on them.
Another bit of speculation is the scale of your objects. I don't know in depth how this work but generally, if physx uses some octree and your objects are too small (all inside one bucket) then collision detection should be slow since it can't efficiently cull away the majority of objects. This is just some thought I had, but I don't know the scale of your game, neither do I know any optimal scale for the physics engine, if any applies.
Thanks. I do have rigidbodies attached to the enemy detector. Here's the hierarchy for each fighter:
-Fighter prefab: script, sphere collider [radius = 0.5] to detect direct collisions with enemies + kinematic rigidbody. Scale: (1.0, 1.0, 0.65). Children of prefab:
a)EnemyDetector (script, trigger-enabled sphere collider of radius 4.0 to "see objects" some distance away, kinematic rigidbody). Scale: (1.0, 1.0, 1.0)
b)Geometry (sphere mesh plus material). Scale: (1.0, 1.0, 1.0)
I have a feeling that Physics.OverlapSphere may still cause issues. But keep in $$anonymous$$d that this slowdown occurs even when no collisions occur (I have breakpoints set in $$anonymous$$onoDevelop), and whether or not the enemy detector is a trigger -- so basically it can't hit anything. The enemy detector's sphere collider size and the fact that it's enabled may cause slowdowns.
I've listed the scale above. I believe its physics engine might get bogged down with scale values besides 1.0.
What does your profiler (if you have access to it) say?
The profiler is off-limits to me as I am using free Unity, unfortunately.
Answer by Julien-Lynge · Aug 13, 2011 at 09:12 PM
Could you do away with the colliders altogether and just use Vector3.Distance.sqrMagnitude calls? In your Start() function, create a list of all the fighters using GameObject.FindGameObjectsWithTag and then iterate through this list? Possibly iterate through on a coroutine that batches the checks so that some subset gets checked every frame? I honestly don't know if 400^2 simple float operations would be faster than 400 collider checks by the physics engine, but it would be relatively quick to try.
You'd be comparing every fighter to every other fighter, so this is definitely going to be slower than octree optimizations (or whatever it uses exactly) that the physics engine has.
I would normally agree with Eric5h5, but strangely enough, this type of test is a bit faster...here's what I did:
--I kept the enemy detector's sphere collider but made it a non-trigger so may detection code does nothing. I made 450 fighters, resulting in 5-6 fps when fighters are NOT being rendered on screen (camera is not facing them).
--I then disabled the sphere collider for the enemy detector entirely, and in the enemy detector's Update() function I wrote similar to the one found here: http://unity3d.com/support/documentation/ScriptReference/GameObject.FindGameObjectsWithTag.html (FindClosestEnemy). Except I found stuff with tag "FighterShip" (shared by friend AND enemy fighters). About 15 fps, again no fighters not being rendered on screen.
I'm not sure why the distance method would work better. $$anonymous$$eep in $$anonymous$$d that it doesn't really scale well though (there are only 450 friendly fighters here, no enemies), so a data structure solution works best....or some kind of batching thing. I wonder how Unity does it...
Your answer
Follow this Question
Related Questions
Help! how to convert input.GetAxis to Accelerometer 0 Answers
Model tips over for no reason 1 Answer
Problem with Colliders 1 Answer
2D 360 degress platformer example needed 0 Answers
How to check is object directly next to another object? 1 Answer