Manual batching of procedural meshes avoiding memory overhead and not preventing VF culling

Hi all, I have a question on how to implement manual batching for point-meshes I generated during run-time procedurally.

They are many point-topology meshes all with the same material. However, since they usually have around 3k vertices (and splitting these meshes is not an option), Unity’s dynamic batching does not work automatically.

I know of two approaches that I could try in such a situation. One is trying to set these mesh objects as being static and then using StaticBatchingUtility.Combine. However, beside Unity not recognizing procedural meshes as static, this solution would incur in great memory overhead since, to my understanding, Static Batching saves an extra copy of the vertices of the meshes that area batched.

The second approach could be Combining all the meshes as soon as they are generated, so then everything would be passed to the GPI in one drawcall. However, this option has the big inconvenience of rendering much much more vertices than needed, since after combining meshes, there VF culling stops leaving vertices out of rendering since some part of combined mesh will alway be visible.

So, the ideal situation for me would be to have a real Dynamic Batching but for meshes with more than 300/900 vertices, which is the non-adjustable threshold in Unity. My question: is there a way to manually do so, i.e. to batch my same material meshes that are generated during run-time with something similar do Unity’s automatic dynamic batching? In other words, where the costs are at the CPU side and not on the memory overhead side like happens with static bashing, but not counting the brute-force combining of meshes which makes me loose VF culling?

Thanks for your insights.

Bumping to check whether anyone has any info on this

I’m bumping into the same problem. Growing a mesh triangle by triangle using a vertex color shader, the shader colors them different so i don’t know if it will be even possible in my case, but i’ll be looking into how to solve it for me.
if i come across any usefull scenario for you, I’ll let you know.

Encountering the same problem here - I’m procedurally-generating a large number of trees which can’t be batched dynamically, but am struggling to find a convenient way to manually statically batch them…

the way i solved it for me is:
generate every triangle as a separate gameobject and use the CombineMeshes function and switch to using vertex colors for mesh.colors…

CombineInstance[] combine = new CombineInstance[allObjects.Count];
        int i = 0;
        while (i < allObjects.Count) {
            combine[i].mesh = allObjects[i].GetComponent<MeshFilter>().sharedMesh;
            combine[i].transform = allObjects[i].transform.localToWorldMatrix;
            allObjects[i].gameObject.SetActive(false);
            i++;
        }
        colors.Clear ();
        foreach (CombineInstance c in combine)
        {
            Mesh m = c.mesh;
            for (int j = 0; j < m.vertices.Length; j+=3) {
               
                    colors.Add (new Color (Mathf.Abs (m.vertices [j].normalized.x),
                        Mathf.Abs (m.vertices [j].normalized.y),
                        Mathf.Abs (m.vertices [j].normalized.z)));
                    colors.Add (new Color (Mathf.Abs (m.vertices [j].normalized.x),
                        Mathf.Abs (m.vertices [j].normalized.y),
                        Mathf.Abs (m.vertices [j].normalized.z)));
                    colors.Add (new Color (Mathf.Abs (m.vertices [j].normalized.x),
                        Mathf.Abs (m.vertices [j].normalized.y),
                        Mathf.Abs (m.vertices [j].normalized.z)));
                }
            }
        }
        Mesh newMesh = visahObj.GetComponent<MeshFilter> ().mesh;
        visahObj.GetComponent<MeshFilter> ().mesh = new Mesh();
        visahObj.GetComponent<MeshFilter> ().mesh.CombineMeshes(combine);
        MeshCollider mc = visahObj.GetComponent<MeshCollider> ();
        mc.sharedMesh = newMesh;
        currentMesh = newMesh;
        visahObj.GetComponent<MeshFilter> ().mesh.colors = colors.ToArray ();