I’m currently reading through the Unity Garbage Optimization guide and I can’t really grasps why this code is different from the better version.
void ExampleFunction()
{
for (int i = 0; i < myMesh.normals.Length; i++)
{
Vector3 normal = myMesh.normals[i];
}
}
void ExampleFunction()
{
Vector3[] meshNormals = myMesh.normals;
for (int i = 0; i < meshNormals.Length; i++)
{
Vector3 normal = meshNormals[i];
}
}
I’m not quite sure myMesh.normals actually do but here is an example of a similar code I wrote for my game.
bool[] isActive;
GameObjects[] bodyParts;
for (int i = 0; i < GameManager.instance.treasures.Length; i++)
{
if(bodyParts[i].activeInHierarchy)
{
bodyParts[i].SetActive(false);
}
else
{
bodyParts[i].SetActive(true);
}
}
So if I get a reference of GameManager.instance.treasures before running the loop will that make a huge difference? Is that what the guide is trying to say?
It’s not quite the same. When you request the normals of a mesh, unity is creating a new array and filling it with the normals. This creates a small amount of garbage. So it’s better to do this once, before a loop, instead of many times within a loop.
In your case, “treasures” is a reference to an existing array/list, so you aren’t creating garbage by referencing it in your code.
1 Like
Unity methods returning arrays copy them to return them. That’s why the first example is improved by the other option of caching the array. For your arrays, unless you told them to make copies to return, that won’t be the same thing.
1 Like
In the general case of calling an accessor property such as .normals, you cannot have any insight into the internal implementation. It could be really expensive, so if you’re just operating on it as a single unchanging array, might as well cache it.
As for your specific .treasures array, if that’s just an array, it would be less of a benefit, but keep in mind that the dot hierarchy has to be traversed each time, since the compiler cannot tell if that might change, so that means many more indirections. In the case of a handful of items it won’t matter, but when you get up to massive scales it could make a massive difference.
As always, run the profiler. Don’t just randomly optimize code just because someone tells you its less-than-optimal. You’re only going to screw up your codebase and make it irritating to work in.
3 Likes
The main confusion is remembering C# loves to use get/set pairs to cover up longer functions. myMesh.normals “feels” like a direct lookup, especially since it’s a get/set pair. But if you think of it as what it really is, which is more like myMesh.buildAndReturnNormalArray(), you can see the problem.
Mesh, from the example, is probably the worst class for this, so that example is pretty specific. You have to pull out the arrays from the graphics card, modify them, then use myMesh.normals=N; to push them all back into the graphics card. It really should be myMesh.setNormals(N); to give a better idea of how it really works. I don’t think any other Unity class has a get/set on an array.
And, sure, run the profiler. But if you know how things work you won’t need to as much.
1 Like
Thanks everyone for the explanations! 
If unity is doing stuff like that it should have been a method not a property. a Method implies it could be a complex operation like o(n) a property does not.