- Home /
Profiler shows Object.ElementAddr_3_8() called over a million times. What is it? How do I reduce this?
I'm working on a voxel game, and in the profiler, under ChunkBehavior.CreateMeshAndCollision()
, I see that Object.ElementAddr_3_8()
is called tens of thousand of times per call of CreateMeshAndCollision()
. It's creating over 70ms of delay every time I create new chunks, making my game stutter. Any idea why Object.ElementAddr_3_8()
is being called so many times?
I appreciate any help. I've dropped my CreateMeshAndCollision()
method below, if you'd like to take a look at it. Thanks!
public void CreateMeshAndCollision() {
vertices = new List<Vector3>();
triangles = new List<int>();
ChunkBehavior topNeighbor = tb.GetChunk(transform.position.x, transform.position.y + SIZE, transform.position.z);
ChunkBehavior bottomNeightbor = tb.GetChunk(transform.position.x, transform.position.y - SIZE, transform.position.z);
ChunkBehavior posXNeighbor = tb.GetChunk(transform.position.x + SIZE, transform.position.y, transform.position.z);
ChunkBehavior negXNeighbor = tb.GetChunk(transform.position.x - SIZE, transform.position.y, transform.position.z);
ChunkBehavior posZNeighbor = tb.GetChunk(transform.position.x, transform.position.y, transform.position.z + SIZE);
ChunkBehavior negZNeighbor = tb.GetChunk(transform.position.x, transform.position.y, transform.position.z - SIZE);
for (int x = 0; x < SIZE; x++) {
for (int y = 0; y < SIZE; y++) {
for (int z = 0; z < SIZE; z++) {
if (blocks[x, y, z] != null) {
bool needsCollision = false;
if (y == SIZE - 1) {
if (topNeighbor != null) {
if (!topNeighbor.BlocksVew(x, 0, z)) {
blocks[x, y, z].CreateTopFace(vertices, triangles);
needsCollision = true;
}
} else {
blocks[x, y, z].CreateTopFace(vertices, triangles);
needsCollision = true;
}
} else if (blocks[x, y + 1, z] == null) {
blocks[x, y, z].CreateTopFace(vertices, triangles);
needsCollision = true;
}
if (y == 0) {
if (bottomNeightbor != null && !bottomNeightbor.BlocksVew(x, SIZE - 1, z)) {
blocks[x, y, z].CreateBottomFace(vertices, triangles);
needsCollision = true;
}
} else if (blocks[x, y - 1, z] == null) {
blocks[x, y, z].CreateBottomFace(vertices, triangles);
needsCollision = true;
}
if (x == SIZE - 1) {
if (posXNeighbor != null && !posXNeighbor.BlocksVew(0, y, z)) {
blocks[x, y, z].CreatePosXFace(vertices, triangles);
needsCollision = true;
}
} else if (blocks[x + 1, y, z] == null) {
blocks[x, y, z].CreatePosXFace(vertices, triangles);
needsCollision = true;
}
if (x == 0) {
if (negXNeighbor != null && !negXNeighbor.BlocksVew(SIZE - 1, y, z)) {
blocks[x, y, z].CreateNegXFace(vertices, triangles);
needsCollision = true;
}
} else if (blocks[x - 1, y, z] == null) {
blocks[x, y, z].CreateNegXFace(vertices, triangles);
needsCollision = true;
}
if (z == SIZE - 1) {
if (posZNeighbor != null && !posZNeighbor.BlocksVew(x, y, 0)) {
blocks[x, y, z].CreatePosZFace(vertices, triangles);
needsCollision = true;
}
} else if (blocks[x, y, z + 1] == null) {
blocks[x, y, z].CreatePosZFace(vertices, triangles);
needsCollision = true;
}
if (z == 0) {
if (negZNeighbor != null && !negZNeighbor.BlocksVew(x, y, SIZE - 1)) {
blocks[x, y, z].CreateNegZFace(vertices, triangles);
needsCollision = true;
}
} else if (blocks[x, y, z - 1] == null) {
blocks[x, y, z].CreateNegZFace(vertices, triangles);
needsCollision = true;
}
/* Don't create collision until we've fixed this problem.
if (needsCollision) {
BoxCollider newBoxCollider = gameObject.AddComponent<BoxCollider>();
newBoxCollider.center = new Vector3(x + .5f, y + .5f, z + .5f);
}*/
}
}
}
}
mesh = new Mesh();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
GetComponent<MeshFilter>().mesh = mesh;
}
Answer by Bunny83 · Apr 17, 2018 at 04:25 AM
ElementAddr_3_8 is the internal method to calculate the flattend array index for your multidimensional array. Since you have a lot array accesses inside the inner most loop you will of course get a lot of these.
You can eliminate some of them by caching the current block at the start of your innermost loop. However for preformance it would be better to use a one dimensional flattend array yourself. Multidimensional arrays are quite slow. When you manually flatten the array you can calculate the intermediate offsets before each nested loop so the index calculation would get simpler.
Though those pure number crunching stuff you may want to carry out on a seperate thread. Just prepare all data required on the main thread and then start the generation. Of course the actual final Mesh creation has to be done on the main thread again.
Alright. I'll try the array flattening and I'll have to look into the upco$$anonymous$$g Unity C# job system or multithreading. Thanks for the quick response! It was killing me to know what ElementAddr_3_8 was.
Your answer
Follow this Question
Related Questions
How do you handle water in voxel games? 0 Answers
Is there a Per-Mesh-Profiler somewhere? 2 Answers
Frame Rate drops when creating mesh in mobile Voxel World? 0 Answers
Issues with profiler? 0 Answers
Size of a mesh vs performance 1 Answer