I have scene with around 2’000 GameObjects representing simple NPC’s which walk around.
The idea behind this is to create a very populated city. But obviously this is a big performance optimization candidate. Since I don’t have much experience with optimizing on Unity I need your help.
Right now I’m checking the distance to the player on each of those GameObjects. If it’s within a certain range all its functions are enabled (movement, renderer, sound). Else its just frozen. All tough I can’t deactivate the gameObject itself because then the distance check would not be executed anymore.
This gives me around 200 draw calls but I still get around 10-15 fps which clearly suggests I’m doing something wrong.
How much load do the distance checks (Vector3.Distance) put on the cpu?
Do you know any other way of solving this?
I’m figuring it would be better to check from the player to the nearest npcs and enable them, thus ignoring the majority of the other npcs beyond reach. But I haven’t figured out how to do that yet.
Right now each of the gameobjects has the following components attached:
- Mesh Filter (using a 2D plane)
- Mesh Renderer (without shadows)
- NPC behaviour script
- Sphere collider
- Audio Source
- Rigidbody (mainly used for gravity)
- Shader (two pass unlit vegetation shader)
Which one of those components would you say is the most performance hungry?
you don’t needfully do something wrong.
You haven’t mentioned what kind of hardware you have and what quality settings you used.
Testing in the editor on Fantastic.
I’m using a MacBook Pro with 2.66 ghz core2 duo and 4 gb of ram. So if it lags for me it will definitely lag for others.
What graphic card?
Fantastic settings are pretty heavy on their requirements, especially due to the anti alias, which is taxing.
Should you have the 8600 or even worse the 9400M based MBP, then going to more appropriate quality settings as Good will surely have a beneficial impact.
Also, the editor is a bad field for testing as the editor does a lot of other things too, thus its performance is definitely lower than in the standalone player.
One thing that might help is to use triggers instead of running 2000 Vector3.Distance checks. Or just check 100 objects every .1 seconds, say, instead of all 2000 every frame (assuming that’s what you’re doing).
–Eric
The trigger thing is really a good idea eric! I’m going to try that.
As for graphics, I don’t think its a graphic issue since most of the gameobjects aren’t even being rendered and I’m having around 200 draw calls.
It really has to do with the distance checks or the fact that unity has to update 2’000 GameObjects every Update.
Since you are just checking the distance is within a certain range, there is a trick you can use that is much faster than Vector3.Distance. This call involves a square root, which is an intrinsically time consuming operation. Instead, try subtracting one position from another and using Vector3.sqrMagnitude to get the square of the distance between them:-
function SquareDistance(ptA: Vector3, ptB: Vector3) {
var diff: Vector3 = ptB - ptA;
return diff.sqrMagnitude;
}
You then need to compare this against the square of the desired range. However, the square root is avoided, so this is much faster than using Vector3.Distance.
Thanks for that info.
I solved it now with a trigger thats parented to the camera. Its pretty effective since you don’t need to see the npcs behind the player anyway.