- Home /
Why is StaticBatchingUtility not completely combining all of my meshes?
I'm trying to create a 3d procedural voxel terrain generator.. I've seen things on how batching will allow for optimization. I've tried the SetActive(); fix that a couple people have suggested, it does not work. Although it does batch, it separates them in to four parts instead of one static mesh. Everything is static, It's in a empty game object called terrain_container. I've tried disabling shadows, lighting, etc.. and I've heard that shaders might be breaking the batching, but I haven't put in any of my own shaders.
This is what it looks like, the combined mesh. As you can see there are 4 separate meshes.. Why?
This is what I'm trying to batch. And my code;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GenerateTerrain : MonoBehaviour {
public static GameObject vox_blank = Resources.Load("Voxels/vox_blank") as GameObject;
public static List<GameObject> Blocks = new List<GameObject>();
public static int Voxels;
public static GameObject[] vv;
public static void Generate(int size_x, int size_y, int size_z){
float voxelScale = vox_blank.transform.localScale.x;
Voxels = 0;
vv = new GameObject[size_x * size_y * size_z];
GameObject terrain_container = new GameObject();
if (GameObject.Find ("Terrain"))
Destroy (GameObject.Find ("Terrain"));
terrain_container.name = "Terrain";
terrain_container.isStatic = true;
terrain_container.tag = "blankVoxel";
for (float x = 0; x < size_x; x += 1) {
for (float y = 0; y < size_y; y += 1) {
for (float z = 0; z < size_z; z += 1) {
GameObject newVoxel = GameObject.Instantiate (vox_blank);
newVoxel.transform.SetParent (terrain_container.transform);
newVoxel.transform.position = new Vector3 (x, y, z);
newVoxel.name = "vox_blank";
newVoxel.tag = "blankVoxel";
vv [Voxels] = newVoxel;
Voxels++;
}
}
}
print (vv.Length + " voxels");
print ("Done terrain");
foreach (GameObject obj in vv) {
obj.SetActive (false);
obj.SetActive (true);
}
StaticBatchingUtility.Combine (vv, terrain_container);
//StaticBatchingUtility.Combine (Blocks.get);
}
}
Answer by Bunny83 · Aug 02, 2016 at 12:40 PM
A Mesh in Unity can only have 64k vertices as Unity uses a 16-bit index buffer. So you can't reference more than 64k vertices in a single mesh.
Creating a gameobject for each voxel is total overkill. You should create the mesh manually. When you create the mesh you also want to remove faces of opaque voxels which are next to each other. Minecraft for example generates chunks of 16x16 which itself is split into 16 sections (16x16 ==256 height). This won't work in Unity since the worst cast vertices count for a single 16x16x16 section that is filled with transparent cubes is 98k vertices. So you would need to use smaller chunks in Unity.
Furthermore MC allows other "meshes" as voxels which might have more than 24 vertices.
I am having the same problem as the OP. I am combining ~600 meshes with the StaticBatchingUtility.Combine. The drawn triangles in the Stats window are not reduced, I even get more draw calls than before. When I look at the Editor view the combined mesh clearly doesn't have its faces weld together, and it is obvious since it will not result in so many tris and verts. All tiles are instances of the very same prefab.
You have 626 submeshes. You should make sure that equal instances should use the same material. $$anonymous$$eep in $$anonymous$$d that you should never touch the ".material" or ".materials" property of a renderer. Only read the shared$$anonymous$$aterial / shared$$anonymous$$aterials. If you read the .material property Unity will automatically create an instance of the material for this instance. In that case you can't batch the instance since it has a unique material.
Note that batching has nothing to do with "welding" vertices, removing vertices or removing faces. Batching is only about combining several meshes with the same material into a single mesh. The batched mesh will have the exact same amount of vertices and triangles, but usually with fewer drawcalls as long as there are instances which use the same shared material.
Thank you, meanwhile after I posted the comment I tried with $$anonymous$$esh.Combine$$anonymous$$eshes and mergeSubmeshes=true which on first glance achieves the same as what the StaticBatchingUtility does. At this point I am not sure if merging submeshes does provide performance boost. However now I don't have any submeshes.
I was wondering if there is a technique of merging (welding) vertices as obviously wherever there are flat surfaces, the triangles can be unified. Triangle count seems to be the biggest performance killer on low-end Android devices.
Thank you!