Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Why does batching break when I instantiate more than one dynamic mesh?

Discussion in 'Scripting' started by highlyinteractive, Oct 24, 2018.

  1. highlyinteractive

    highlyinteractive

    Joined:
    Sep 6, 2012
    Posts:
    94
    I am trying to get GPU instancing working in a pretty simple scene. I am creating two meshes and giving them a single material. The material uses a standard shader with 'Enable GPU Instancing' checked. I then instantiate a grid of these.

    Here is my code:

    Code (CSharp):
    1.  
    2. private GameObject _prefabA;
    3. private GameObject _prefabB;
    4.  
    5. private void Start ()
    6. {
    7.         _prefabA = CreatePrefab(true);
    8.         _prefabB = CreatePrefab(false);
    9.  
    10.         for (int x = 0; x < 20; x++)
    11.         {
    12.             for (int y = 0; y < 20; y++)
    13.             {
    14.                 InstantiatePrefab(_prefabA, (x - 10) * 2, (y - 10) * 2);
    15.                 InstantiatePrefab(_prefabB, (x - 10.5f) * 2, (y - 10.5f) * 2); //comment out this line to drastically reduce draw calls
    16.             }
    17.         }
    18. }
    19.  
    20.     private GameObject CreatePrefab (bool isUp)
    21.     {
    22.         Vector3[] verts = new Vector3[3];
    23.         Vector3[] norms = new Vector3[3];
    24.         Vector2[] uvmap = new Vector2[3];
    25.  
    26.         float px, py, off = 0;
    27.         float radius = 3f;
    28.  
    29.         for (int i = 0; i < 3; i++)
    30.         {
    31.             if (isUp) off = Mathf.Deg2Rad * 180;
    32.             px = Mathf.Sin((Mathf.Deg2Rad * 120 * i) + off) * radius;
    33.             py = Mathf.Cos((Mathf.Deg2Rad * 120 * i) + off) * radius;
    34.  
    35.             verts[i] = new Vector3(px, py, 0);
    36.             norms[i] = new Vector3(0, 0, -1);
    37.             uvmap[i] = new Vector2(px, py);
    38.         }
    39.  
    40.         GameObject go = new GameObject("prefab_" + (isUp ? "up" : "down"));
    41.         Mesh mesh = go.AddComponent<MeshFilter>().mesh;
    42.         MeshRenderer ren = go.AddComponent<MeshRenderer>();
    43.         ren.material = Mat;
    44.         go.SetActive(false);
    45.  
    46.         mesh.vertices = verts;
    47.         mesh.normals = norms;
    48.         mesh.uv = uvmap;
    49.         mesh.triangles = new int[] { 0, 1, 2 };
    50.  
    51.         return go;
    52.     }
    53.  
    54.     private void InstantiatePrefab (GameObject prefab, float x, float y)
    55.     {
    56.         GameObject go = Instantiate(prefab);
    57.         go.SetActive(true);
    58.         go.transform.position = new Vector3(x, y, 0);
    59.         MeshRenderer ren = go.GetComponent<MeshRenderer>();
    60.         ren.material = Mat;
    61.     }
    62.  
    This results in 239 batches and 562 saved batches.

    However, if I only instantiate one of the two prefabs, I get 2 batches and 399 saved.

    Why is this?

    In the original example, the frame debugger suggests that a large number of the meshes can't be batched because the mesh is different. Would be great to understand why this is happening - can anyone explain it to me?

    Edit: Material is transparent. Turning it opaque reduces the draw calls to 7. I don't really understand why transparent materials can't be batched as effectively though, so would still love to get some knowledge from someone with a little more experience.
     
    Last edited: Oct 24, 2018
  2. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    866
    Transparent objects need to be sorted based on depth in order for them to draw in a back to front order. I guess the gpu instancing has real trouble with this, especially if you mix the two kinds of objects spatially, you would need to split the draw call in order for things to sort properly.
    Not sure what you can do about it without making them opaque or just using one kind.
     
    SparrowsNest likes this.
  3. highlyinteractive

    highlyinteractive

    Joined:
    Sep 6, 2012
    Posts:
    94
    Thanks for the insight
     
unityunity