I’m hoping to optimize some of the scripting in my game. For my first problem, I noticed the profiler reveals 6.4% CPU from one type of script. It’s a custom LOD script that runs in FixedUpdate().
(LOD_Simple.FixedUpdate is the subject in question) The intent of the LOD script was to cut down on the Camera.Render percentage, but it seems my distance calculations are starting to take up a lot of CPU. (There’s a lot of instances of this script on many objects, and I’m not even done with the objects in the scene) The script is fairly simple, it is basically this but with a few more boolean checks (that are cached at startup)
function FixedUpdate ()
{
isAngle = Vector3.Angle(t.position - cam.position, cam.forward) <= cam2.fieldOfView + 20;
var curDist = Vector3.Distance(cam.position, t.position);
if (curDist > dist1 || (!isAngle && curDist > dist1 * .5))
{
myRenderer.enabled = false;
}
else
{
myRenderer.enabled = true;
}
}
As you can see, I’ve cached every Type I could ever need for this script. The Renderer, Transforms, and Camera are all local variables. All it does is check Distance and Angle and disables the renderer. (In some cases it also changes out the Mesh for a simpler version) Thinking through this, I know that the most efficient calculations are the ones that don’t happen at all. But it’s not like I can just stop calculating distance. The camera could be anywhere at any time.
Another solution could be to use collision data and triggers instead, but I’m worried about whether that’ll really be more efficient. As the profiler noted, Physics and Collision data is taking a big chunk out of CPU already. And using a Trigger system would result in a lot of instances of dynamic Colliders. So there must be a more efficient way to calculate Distance and Angle, right? Or is there a more complex solution I’m not seeing here? Is there something else that will allow me to switch the renderer with a lower cost?
Problem 2: AI scripts use Raycasts to detect their targets. So I store a list of targets and loop through each one with the Raycast. (Distance is done first so it gives up if targets are out of range) Something like this:
function FixedUpdate () {
for (var i = 0; i < elen; i++)
{
var curEnemy = enemies[i];
var curDist = Vector3.Distance(transform.position, curEnemy.transform.position);
var curAware = enemyAwareness[i];
if (curDist <= maxDist)
{
//raycasts and junk
}
else
curAware = 0;
}
}
I could do this easily with culling (distance from player) and by limiting the targets to a few for each enemy. I only had to do specific targets. But now a new enemy type requires me to do these checks for all characters! Which means a LOT of looping, I’m worried the same thing will happen as the LOD script. Except instead of just checking one transform, it has to check over 30! I thought I might get around it by only looping through closest characters, but that still requires a distance check to see who is close! There must be a more efficient way to get the closest couple of characters without checking against everyone for every FixedUpdate right??
Note: I’m using the fastest type of loop (to my knowledge) which is the for i = 0 etc. And I’m caching array length (i < elen) so I don’t have to reference it every time. But there must be more I can do to improve the performance of looping, even if looping ends up being the wrong choice for optimization, I would like to know in general if there’s a better way.
Thanks in advance! Lastly, I was wondering exactly what “Overhead” is? It’s taking up 7% and I have no clue what it even does!