[Unity 5 version available] Runtime Mesh Batcher - Simple and affordable batching system

Hello there!

My name is Georges Dimitrov, I’m a music composer, professor, and indie video-game developer from Montreal, Canada. While working on my current game (an old-school dungeon crawler), I ran into the problem of draw calls related performance issues, because my levels are all constructed at runtime from Lua scripts. I found many great assets on the store, such as Mesh Baker, but all of them focused on tools to prepare your scene while in the Editor, including things like Lightmapping support, which I obviously didn’t need.

So I developed a simple system for combining meshes, system which is designed and optimized for runtime usage, and put it on the Asset Store, as I think others might benefit from the performance improvements, which were fantastic in my game, bringing some scenes from over 30K draw calls down to an acceptable range of a thousand or two, while more than doubling frame rate.

I plan to actively continue development on this project; I have already updated the script to v1.1, adding for example the option of uncombining meshes (see changelog below). If you have any questions or comments, don’t hesitate to post!

Asset store link: Unity Asset Store - The Best Assets for Game Making

Asset Description

Runtime Mesh Batcher is a script extension for Unity which provides an affordable, easy and fast way to combine multiple individual meshes at runtime, reducing draw calls and improving performance.

While other solutions available on the Asset Store offer greater in-editor capabilities and much more options, this script is specifically designed to provide a plug-and-play solution for games which create their environments procedurally at runtime.

  • Clean and professional code.
  • Works with Unity or Unity Pro.
  • Custom inspector.
  • Automatic Batching mode through custom Tag or Layer.
  • Manual Batching mode for advanced scenarios (by providing a GameObject array).
  • Can be used with a controller GameObject for setting options in the Editor or directly from script.
  • Fast and optimized operation: combines 100K individual meshes in under a second.
  • Combines complex object hierarchies with multiple materials.
  • Automatically handles Unity’s 64K vertex limit - you can combine an unlimited number of meshes without worries.
  • Batching process is reversible (v1.1).
  • Clear documentation.
  • Demo scene provided.

Video Demonstration

Manual

If you wish to have more info about how it works, you can download the manual in PDF format:
http://www.georgesdimitrov.com/wp-content/uploads/Runtime-Mesh-Batcher-Manual-V1_2.pdf

Changelog

Version 1.1

IMPROVEMENTS:

  • Created combined meshes are now parented under distinct GameObjects incrementally named "RuntimeMeshBatcherParent_n”, allowing to easily find them in the hierarchy if needed.
  • RuntimeMeshBatcher.CombineMeshes now returns the newly created parent GameObject. You can keep that reference around to do things with the combined meshes, for example delete or deactivate them, or uncombine them.
  • Added “Destoy original objects” option, if you do not need to keep the original GameObjects for purposes like keeping the colliders on them (false by default).
  • Added “Keep original object references” option, which enables a new UncombineMeshes method to reverse the process (false by default to save memory if you do not need the functionality).
  • Added RuntimeMeshBatcher.UncombineMeshes(rmbParent) which you can call with the reference to the parent object, to undo the batching process.
  • Original GameObjects transform hierarchy is now preserved after the batching.
  • Added tooltips to the custom inspector.
  • Some performance optimizations to the code.
  • Updated documentation.
  • Updated demo scene with new UncombineMeshes option.

FIXES:

  • Small error in the demo scene prefab could cause an undefined Tag error.
  • Removed usage of transform.SetParent to make the script backwards compatible with pre-4.6 versions.

Version 1.0

Initial Release

Hello,

I’ve just updated the Runtime Mesh Batcher to Version 1.2. The main new feature (added after a user request) is the new option to batch objects together following a grid, making many smaller meshes instead of huge ones. This may result in a lesser draw calls reduction, but allow different culling procedures, such as frustum culling, distance culling or other custom culling scripts. Depending on your situation, this may provide a better performance.

Changelog for Version 1.2:

NEW FEATURES:

  • Added new option to batch objects in separate meshes following a grid, allowing frusturm or distance culling.

IMPROVEMENTS:

  • Added platform dependent compilation code to use “transform.parent =” for Unity 4.5 and “transform.SetParent()” for Unity 4.6. This keeps compatibility with Unity 4.5 and before while avoiding unnecessary warnings on 4.6.
  • Updated documentation.

If you have any questions or comments, don’t hesitate to post!

Hi,

Runtime Mesh Batcher was updated to 1.2.1, a minor release to fix a crash that could occur if objects were sent to batching which didn’t have meshes on them. I’ve also added an option to “autorun” it at startup, if you wish to use it just with the prefab and the inspector window to batch scenes built in the editor, without the need for any scripting.

You can get the update here: Unity Asset Store - The Best Assets for Game Making

Changelog for Version 1.2.1:

NEW FEATURES:

  • Added an option to the RuntimeMeshBatcher inspector Controller to automatically batch objects at startup, if the batching is to be done only on meshes created in the editor, not at runtime.

IMRPOVEMENTS:

  • Updated documentation.

FIXES:

  • Fixed a crash which could happen if a gameObject sent to RuntimeMeshBatcher had no MeshRenderer components on it or its children.
  • RuntimeMeshBatcherParent objects weren’t properly named in an incremental way.

Georges,

I’m using your scripts in my game to combine tree meshes. It works, but the trees are missing their leaves. I’m using the Unity standard palm tree asset which has two materials “palmbark” and “palmbranch”. When the meshes are combined only the “palmbark” is being included. So the trees just have trunks, no leaves.

Can you fix this?
Thanks.

Sure, I’ll look into it and get back to you as soon as I find what’s wrong.

Hi NunSuperior,

There was a problem with how meshes that contain multiple submaterials (like trees) were handled, sorry. I’ve fixed it and it now seems to work fine with trees when I test it here. If you send me your e-mail in a PM or e-mail me directly, I can send you an updated version of the script to test, and if it’s allright, I’ll update it on the asset store.

Thanks for the feedback!

Hi,

Runtime Mesh Batcher was updated to 1.2.2, a minor release to fix the issue reported above. The system now handles submaterials as it should. There’s also a couple of small improvements which were suggested by NunSusperior, thanks a lot!

You can get the update here: Unity Asset Store - The Best Assets for Game Making

Changelog for Version 1.2.2:

IMRPOVEMENTS:

  • RuntimeMeshBatcher parent objects are now all parented under the GameObject that has the RuntimeMeshBatcherController script, or if it is not used in the scene, under a single “Container” object.
  • **RuntimeMeshBatcherController**.instance.CombineMeshes now supports passing a GameObject array to it, while using the rest of the options set up in the inspector. **RuntimeMeshBatcher**.CombineMeshes could already work with custom arrays, but you had to manually supply the options in code.
  • Updated documentation.

FIXES:

  • Meshes which had multiple sub-materials weren’t handled correctly, resulting in parts of the meshes being discarded. This is no longer the case.

Hi,

I’ve just uploaded a Unity 5 version of Runtime Mesh Batcher on the Asset Store, so it’s all been tested and works great.

Unity 5 has better dynamic batching system than Unity 4, but I still managed to achieve much higher frame rates on my demo scene with the RMB. And the dynamic bathching isn’t saving much FPS anyway as the saves on rendering seem to be spent in CPU.

Unity 4 stats:
Before: 13736 Draw Calls, 33 FPS, 13ms on Renderer
After: 29 Draw Calls, 68 FPS, 0.2s on Renderer

Unity 5 stats:
Without Dynamic Batching Before: 29376 Batches, 22 FPS, 16.9 ms on Renderer
With Dynamic Batching Before: 97 Batches, 20 FPS, 11ms on Renderer
After: 49 Batches, 63 FPS, 0.4ms on Renderer

Hi,

I have some questions, i hope you will help me !

○ Could i using this asset with static environment like race tracks with colliders (like road mesh colliders…) ?

○ I am using Unity 5, If i am not using RMB then my stats (Tris: 40.0k, Verts: 50.3K). But when i am using RMB then see after stats (Tris: > 80.0k, Verts: >100.0k), its double Tris and Verts numbers. And why it like that ? Could you fix this ?

○ I wish you can add more features in the future. And more improvement for Unity 5 support. Of course, i hope you will maintain this asset ad don’t stop develop this !

Waiting for the next updates !

Thanks

Could anybody tell if this asset works on javascript projects?

Hi CoderPro,

Of course, this is meant for static environments. What it does is that it disables the mesh renderers on your original objects, and adds a new object with a huge combined mesh on top of them. But the objects remain as you made them, including any colliders you might have on them. So I guess that the MeshCollider would still work since the mesh is still there on the object, just not rendered. I haven’t tested it with MeshColliders though, so I can’t be 100% sure - I’ll test and report back.

About the doubling of tris and verts, yeah that’s just how Unity’s MeshCombine function works. I can investigate further, but generally graphic cards can happily live with 2x the polygons if they have 100-1000x less draw calls so it’s a good trade.

And don’t worry, I’ll keep on developing it!

angel_m, I got your email too, was about to respond. Yes, you should be able to use it from javascript. You could either:

  1. Place the entire RuntimeMeshBatcher folder in a plugins folder so that it gets compiled first ( see Unity - Manual: Special folders and script compilation order), useful if you want all scripting functions

  2. Or use GameObject.Find(“RuntimeMeshBatcherController”).SendMessage(“CombineMeshes”), much simpler solution if you use the prefab and set up your options with the inspector.

Ok, thanks.
I have tested the demo scene and it seems as the “Uncombine meshes” button does not work. Is not possible to uncombine the meshes in the editor to recover the individual meshes if needed?

Make sure “keep Object references” is checked, or uncombine doesn’t work…

Thanks for your keep on developing !

About the doubling of tris and verts, I am developing game for mobile devices only. So, i am worry that, if i run on mobile devices, the game performance will be not good. I thing still need fix that. Could you fix it ? or noway to fix it ? Hope you help me !

Hi, I have a question about this asset. Let’s say I’m going to instantiate a tile map at runtime with hundreds of quads each with its own texture (all randomly generated), will I be able to combine the quads to one mesh and all the different textures into one single texture/material at runtime, after tile generation without any limitations?

@CoderPro , I’m not sur if anything can be done. I’ve remade some searches and based on this: http://answers.unity3d.com/questions/502700/mesh-combine-increases-triangle-count.html it seems that the mesh itself is not doubled, but somehow the statistics windows reports more tris being sent to draw. I know that I’ve seen changes to those numbers when you turn on dynamic shadows for example… In any case, you should probalby come out ahead if you are using a very large of number of objects, the draw call reduction is worth it.

@betaFlux , right now my asset does not combine textures/materials, only meshes, which it combines per material. So if you have hundreds of different materials, you’ll end up with hundreds of meshes, so basically it would be pointless. I might consider including texture combining, but part of the point with this asset was to provide a clean and simple solution that does one thing right at 5$, versus things like MeshBaker which at 55$ does material combining, atlases, handles prefabs and baked lightmaps and so on.

Would adding the runtime texture combine functions and raising the price of the asset to 10$ would be a good idea for you guys, or would you rather keep it like it is? Or I could do a Runtime Mesh Batcher Pro separate asset with texture capacities?

I hope you will not make a Runtime Mesh Batcher Pro separate asset. And the ideas about combine textures are not good. I can not make and use normal map, specular map for that atlas textures. So, i hope you will not make a separate asset like that.

I just came here to ask a question, and your answer to angel_m solved it. Thanks!

@theorherkaki, great! Happy it works.

For everyone, I haven’t updated the asset in the last month or two, as it’s mostly doing fine what it’s supposed to do. But I would be happy to continue developing it, so are there any features you would like to see?

Does this system work with sprites?