Dynamic Batching Failing in Simple RTS game

(I couldn’t come up with a better title for this question - please let me know what I could add to make it better.)

I know questions about Dynamic Batching have been asked to death, but I haven’t been able to determine what’s causing the batching to break in my game.

My game uses a grid of planes for the terrain. These planes can move around during the game, so they’re not static. The size of the grid is 900 planes (30x30). When the game contains just the grid and UI (background and foreground), the planes are batched and I end up with 3 draw calls. Perfect.

During the course of the game, the grid can get “colored in” by different players. When the planes get colored, I swap their material to a player-specific one. With 4 players, I get 5 draw calls (not including the UI) - one for “neutral” planes, and one for each player. Again, perfect.

This is an RTS game, so players build structures. There are a variety of structures, but all structures for a player use the same material. Some of the structures are composed of multiple meshes, but they’re all under 150 vertices (the largest is around 117 vertices). When just the structures are drawn (with no terrain), I get 4 draw calls - one for each player. Still perfect.

The problem comes when the structures and terrain are both drawn - it jumps to nearly 400 draw calls. I have absolutely no idea why, but here’s everything I’ve done as I’ve seen different solutions around:

  • Everything is scaled uniformly - (1,1,1) through the entire hierarchy.

  • Mesh Filters / Mesh Renderers are all on the same layer (“Default” for now). Colliders are in separate GameObjects with different layers. (I’m not sure if this makes a difference, but I saw a few references to layers with batching and gave it a try)

  • The materials on the mesh renderers aren’t instances - I’ve checked, and “(Instance)” is nowhere to be found. They all appear to be using the same material properly.

  • All my materials are simple Unlit or Unlit/Colored, so there’s no transparency. I can’t remember if Unlit/Colored was included or if I wrote it myself. In case I wrote it myself:

     Shader "Unlit/Colored"
     {
     Properties
     {
     	_MainTex ("Base (RGB)", 2D) = "white" {}
     	_Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
     }
     
     SubShader
     {
     	Tags { "RenderType"="Opaque" }
     	LOD 100
    
     	Pass
     	{
     		Lighting Off
     		SetTexture [_MainTex]
     		{
     			constantColor [_Color]
     			combine texture * constant
     		}
     	}
     }
     FallBack "Unlit"
     }
    
  • The planes themselves can sometimes swap textures without changing ownership. When this happens, I swap the mesh for one with different UVs. This is working as expected, and doesn’t result in an extra draw call (when only showing the terrain, at least).

Let me know if there’s any other information I can provide that will help.

EDIT

So I’ve done some experimenting to see if I can figure out what the real problem is, and from what I can tell, it has something to do with the positioning of the different meshes. Even though they all share the same material, if the different meshes aren’t positioned in a certain way, they won’t be batched. Does the relative position of the different meshes affect batching?

For instance, in the following shots, I have two different meshes - one is a half-spherical dome and the other is a simple 4-vertex plane. They’re both using the same material (my atlas). Between the images, all that changes is the position of one of the meshes. Aside from that, I was under the impression that the meshes would be batched together, despite being different, so it should only use one draw call instead of the 2 or 3 shown here.

2 draw calls:

716-2DrawCalls.png

3 draw calls:

717-3DrawCalls.png

I got a solution to this problem on the Unity Support forums:
http://forum.unity3d.com/threads/133862-Dynamic-Batching-Failing-for-RTS-Game

The problem here was with the parenting of the objects - I didn’t know the parenting could affect batching. I’m using Path-o-logical’s PoolManager to pool my objects, and I had each of my pools under a root “Pools” GameObject:

Pools
-TerrainPool
--(Terrain Objects)
-StructurePool
--(Structure Objects)
-Etc...

Getting rid of the root object and renaming my pools (purely for organizational purposes) solved my problems:

-Pool-Terrain
--(Terrain Objects)
-Pool-Structures
--(Structure Objects)

(Thanks to Petroz and Glockenbeat on the forums for the solution)