How to get Dynamic Batching to work?

Hi,

I read a bit now about dynamic batching and am pretty confident that everything is setup right so far.
I have enabled Dynamic Batching in settings, I am batching a lot of small objects (24 verts, 12 tries each) with the same single material set with renderer.sharedMaterial… The material is not updated.

Now I have thousands of these things on screen, all with rigidbodies, colliders, meshrenderer and stuff… But batch count stays zero and draw calls stay at a few thousands ;).

How can this be?
After all this is causing some trouble now even though we already doing static batching as soon as the rigid bodies go to sleep… But when they are moving it easily hits the draw call limit…

Any help would be really appreciated!

there are multiple ways:

  1. you use lightmaps
  2. you don’t use uniform scaling (try with no scaling at all aside of the default 1 1 1)
  3. the material is transparent which has impacts on batching
  4. they are not meshes but skinned meshes and have skinned mesh renderers which will not batch at all
  5. same goes for softbody stuff.
1 Like

Neither of this is the case…

Here is the code generating a fragment of the kind above… That is all what’s happening…

if (SceneNode == null)
{
var mesh = new UnityEngine.Mesh();

mesh.vertices = Vertices;
mesh.uv = mesh.uv2 = UVs;
mesh.normals = Normals;
mesh.tangents = Tangents;
mesh.triangles = Triangles;

// create scene node…
SceneNode = new GameObject();
SceneNode.transform.parent = ParentTransform;
SceneNode.transform.localPosition = MapRelativeBlockPos.ToVector3();

SceneNode.name = “::smile:etachedFragment”;
SceneNode.layer = (int)Layers.Player;

SceneNode.AddComponent().mesh = mesh;
SceneNode.AddComponent();

var rigidbody = SceneNode.AddComponent();

rigidbody.mass = 0.1f;
rigidbody.sleepVelocity = 1;
rigidbody.sleepAngularVelocity = 1;
}

// add the expensive components we usually want to avoid…
if (SceneNode.GetComponent() == null)
SceneNode.AddComponent().sharedMaterial = Material;

No sorry… Was code back a while. Parent doesn’t have scaling in this version anymore. So that can’t be the reason!

If you’re generating meshes yourself, it may be necessary to set renderer.sharedMaterial to the same material too, in order to get batching. I am assuming you’re working with very low polygon meshes and aren’t using different shaders or different scales between them.

Yes all have scale (1,1,1) throughout the whole transform hierarchy. All the same material, set through renderer.sharedMaterial…

Still doesn’t work. Any requirements on the material? Its a non-transparent surface shader in opaque queue and some sort of detail/normal/parallax mapped shader but that shouldn’t matter? It has four textures… All material parameters are static.

I now even disabled shadow casting/receiving on these materials… Still no difference…

Uhh I found something out:

Switching to “VertexLit” rendering path enables batching…
But it doesn’t work for Forward/Deferred rendering.

How can that be?

Seems like UT is threading dynamic batching as an issue of mobile devices? I am not quite sure where they get this from. When destroying buildings ala APEX then there will be up to tens of thousands fragments flying around and the limit of 5000 draw calls per frame is just nothing… This truly cries for dynamic batching and this can only be performed efficiently within the rendering pipeline and not from script… But I hope that this isn’t a joke that only VertexLit supports dynamic batching?

Looks like it was also discussed here: http://forum.unity3d.com/threads/62714-Batching-HOWTO/page3

But I still don’t have the right answer… Is dynamic batching supported in Deferred rendering?!
Also I don’t get it why it is a problem at all… What’s the difference between putting vertices into one large buffer and rendering a lot of small buffers? As long as they are order independent, which is the case if they are not transparent… I mean putting them into one buffer obviously works for us in case of our own static batching, in deferred rendering. Why can’t Unity do this automatically?

And even when there are occasions in which it leads to wrong results. Who say that dynamic batching has to be done? They could then just provide some sort of boolean value for mesh renderers making them available to dynamic batching and then the developer is responsible if something goes wrong…

The material must be simple enough. as soon as the shader you use requires more than 1 pass, the batching will break.

so for diffuse it should work for example.

in cases where batching is not done, its not done cause doing it would cost more performance than it saves → hence useless
(or cause its technically not doable - alpha material batching due to depth sorting for example)

At least so far there is nothing in the shader that should cause more than one pass. But maybe it is still too complicated for what reason ever, since using a simple shader solves it in some ways…

Do you know if batching is supported at all in deferred rendering, in Unity 3.4?

Just verified: Switching to “Mobile/VertexLit” shader, which should be quite simple enough does still not trigger batching in deferred rendering :(. It DOES work in forward rendering with such a simple shader, but who needs that? Don’t really care about forward rendering anyway so I suppose I will also have to write a custom dynamic batcher for deferred rendering?! Also the batching, if it works, is not very efficient. the draw calls go down from 4000 to 1200, even though only 24 vertices are used per mesh… The main issue then is the physic engine which seems to eat up all CPU but thats because the optimizations we have are not ready right now.

So maybe the conclusion, as for Unity 3.4, unless someone has something to add or correct ;)…

  1. Dynamic batching does work well for VertexLit rendering path
  2. It does work for Forward Rendering if the shaders are very simple, like Mobile/VertexLit
  3. It NEVER seems to work for deferred rendering
  4. Even if it does work, it seems to work “mobile” specific, which means judging by the quite disappointing draw call reduction of only a factor 3-4, which is somewhat ridicolous given the fact that we have an “optimal” setup for batching (a lot of small fragments with the same material). For PCs a much higher vertexcount per batch would be possible and urgently needed, since even with batching Unity soon hits the 5000 draw call limit… Which is a little weird since it should “know” that it is better to put more meshes into each batch instead of having a framerate of one; can’t get worse so to speak…
    Besides putting more meshes into a batch on PC platforms, it could be further optimized by propagating items that have not moved during last frames into another generation (a more static batch).

And please let us optionally enable batching in deferred rendering for individual object groups or transform hierarchies, by letting us decide if the resulting visual artifacts, if there are any, are acceptable or not…

Because this is one of the first Google hits for “Unity Dynamic Batching not working” I though I would bump and add that using real-time Shadows will generally prevent dynamic batching as the objects need to be rendered again from the light’s perspective as shadow casters/receivers (two separate passes) therefore they can’t be batched dynamically.

Often (in deferred rendering mode) this even prevents batching for materials/objects that are not shadow casters/recievers (vertex lit ect) or have have shadow casting/recieveing options disabled although I have no idea why. What’s even more bizzare is that dynamic batching still seems to work when shadows are enabled for transparent materials in deferred mode but only if they have both cast and receive shadows options ticked in the mesh renderer options - disable just one of them and no more batching!?? I have no clue why this happens, "It just does"™.

The dynamic batching black-box in 3.4’s deferred mode seems rather wonky.

Uhhh yea , this dynamic batching seems pretty messed. Im using simple planes , with a diffuse suface shader , no transparencies what so ever, and only non important SH lights , and not one thing will batch. In forward.;

how many vertices do the planes have? are they the unity prefab ones, they’re constructed out of many triangles, it might be over 300 verts.

Nah not at all , i mean planes , out of max O.O (not quite a plane , been seg extruded once , still 16 - 20 verts a peice…

(bookmarked)

Batching is something totally independent of whatever you do with the rendering. As long as you don’t need to preserve draw call order for some reason, say transparent shaders, rendering all objects with the same material in one call or in thousand calls makes no visual difference.

The saying goes, “better make a few more draw calls, than having to copy geometry around in every frame”. Okay, but when I hit the 4000 draw call limit, then this does not hold anymore. Because basically what we have then is “Better copy huge chunks of geometry around every frame, than having an unplayable game”… Unity definitely needs to adopt this latter philosophy, especially since copying geometry in optimized C++ is very fast compared to what you can do with the stupid UnityEngine.Mesh and C#.

Or make it even easier. Just add a material flag “ForceBatching” which relieves Unity of any responsibility regarding visual artifacts. So if we NEED to do dynamic batching for performance reasons, then you should allow us to. Because as I said, rather some artifacts or wasted CPU performance than an unplayable game!

1 Like

I just stumbled over this thread searching for an answer.
Can someone confirm this: I create a new scene and add 5 default cubes inside Unity, hit play and the stats give me 5 draw calls.
But all cubes are using the same material, default diffuse.
Shouldn’t batching work then?

UPDATE: I recreated the scene in a freshly created project - and there it works.
Is something in my project settings responsible for this?

You need to check “Dynamic Batching” in player settings. But anyway it is weird that this works. Try it with deferred rendering or more complex materials ;). I mean who has a bunch of boring cubes in his game. In real life, batching doesn’t work!

@ImogenPoot: Thank for your answer, the setting was on but I somehow missed that the “cast shadows” setting seems to break batching…