informa
3 min read
article

Unity 3D: Batching independently moving GameObjects into a single mesh to reduce draw calls.

Using Unity's SkinnedMeshRenderer to batch multiple separate moving GameObjects into a dingle draw call.

I discovered some black magic for batching to reduce draw calls in Unity recently. Think you can't combine and batch objects that move independently? You can.

You probably know that static 3D models - things that never move at all - can be marked as Static and get automatically batched by the graphics engine. Separate meshes, as long as they use the same material with the same shader, can be combined into one draw call, which means less work for the graphics card (although I'm no expert on how this stuff works exactly).

I have a game where you build vehicles out of lots of of smaller parts. All parts on the vehicles use the same material. All the part textures are baked into one big texture atlas image, and data in the vertices of the parts themselves determines whether they're shiny or dull, or damaged, or hot - allowing the whole thing to use the same single shader.

But that's not enough to get batching working on its own. Unity can do a small amount of dynamic batching - batching for objects that aren't Static - but its limit is only a few hundred polygons. One vehicle part has a few hundred already.

One thing I was already doing is taking all the parts on a vehicle that don't move (I mean, the whole vehicle moves, but those parts all move together with it) and combining them into one big combined mesh when players entered a game. Having one combined mesh is the final tipping point to getting everything batched and reducing the draw calls. (When parts get destroyed I zero the appropriate ones out.)

That helped, but I couldn't combine anything that moved on its own, like weapon turrets and spinning fans, and there was still a lot of that.

Here's the trick, and I know there are others out there searching for the same powers I was searching for. Even batching stuff on the Asset Store often does less than this.

You can combine everything, and have the GPU do the transforms directly on the vertices of the parts that move to put them wherever they need to be. Create one model and change the model as you go. You could write a shader to do it, but you don't even have to, because Unity has built-in support for it. Ever used SkinnedMeshRenderer to animate something with bones? The transforms of the separate moving vehicle parts can be the bones! The Unify Wiki even has an example of how to do the conversion!

So now I combine everything, and it's super fast. There is a little bit of overhead in doing the transforms: People with DirectX11 or newer cards, you'll be doing it on the GPU (check your Player settings in the Editor for the checkboxes to enable this and DX11 mode). Those with DX9 or DX10 cards will be doing it on the CPU. But it's a small amount of extra work either way compared to the gains in total performance - at least in my use case.

Latest Jobs

Treyarch

Playa Vista, California
6.20.22
Audio Engineer

Digital Extremes

London, Ontario, Canada
6.20.22
Communications Director

High Moon Studios

Carlsbad, California
6.20.22
Senior Producer

Build a Rocket Boy Games

Edinburgh, Scotland
6.20.22
Lead UI Programmer
More Jobs   

CONNECT WITH US

Register for a
Subscribe to
Follow us

Game Developer Account

Game Developer Newsletter

@gamedevdotcom

Register for a

Game Developer Account

Gain full access to resources (events, white paper, webinars, reports, etc)
Single sign-on to all Informa products

Register
Subscribe to

Game Developer Newsletter

Get daily Game Developer top stories every morning straight into your inbox

Subscribe
Follow us

@gamedevdotcom

Follow us @gamedevdotcom to stay up-to-date with the latest news & insider information about events & more