- Support >Unity 5.1, Unity 2017.x, Unity 2018.x and Unity 2019.x.
- Supports all platforms (PC, Mac, Linux, Android, IOS, WebGL, etc).
- Can be used on the in Editor and/or Runtime.
Here is a demo build of an example Scene from a popular modular Asset called Dungeon Architect. MCS boosts performance about 2170%! (from 37 to 805 fps) on my Nvidia 980TI compared to Unity’s batching:
MCS Dungeon Architect demo
3.How does it work?
Simply drag and drop the MeshCombineStudio prefab into your Scene. You can use multiple MCS prefabs for different settings in the same Scene. if you use MCS in runtime, make sure you disable Unity’s static batching or disable ‘batching static’ on the MCS to combine GameObjects. Otherwise Unity static batching will combine the meshes instead and MCS won’t work.
MCS is completely automated like Unity’s static batching and you don’t need to do tedious manual combining. MCS works with a clever octree cell based combining technique which is optimal for culling, z-sorting and LOD switching. What is unique about MCS is that it support LOD meshes and that MCS is able to remove geometry that is never visible for the camera. E.g. triangles that are under a terrain/mesh, and/or backface triangles on background terrain or on a sideway scroller or top down game. LODs are combined per cell and switching is done per cell. This gives even more performance and as a bonus gives less LOD popping artifact.
The MCS script Inspector is divided into seven parts: Unity’s settings, Search Options, Output Settings, Job Settings, Runtime, Execute Buttons and Stats.
These are Unity settings from Unity Menu (Player and Quality Settings) to quickly access them.
Enable/Disable Unity’s static batching (same setting as in Player Settings). More info on Unity’s batching can be found in the Unity Manual here.
Enable/Disable Unity’s dynamic batching (same setting as in Player Settings).
V Sync Count
Enable/Disable Unity’s V Sync Count settings (same settings as in Quality Settings). Disable V Sync to measure true fps gain, otherwise Unity will cap to 60 fps.
With the search options you can filter which GameObjects with meshes MCS will combine.
The GameObject parent in which the meshes in the children will be included and combined.
What position should be used to determine in which cell the mesh will be placed, the center of the mesh bounds in world space or the transform pivot.
Draws the combine cells in the Scene window after objects are found for combining when clicking the ‘Search’ button.
Draw Mesh Bounds
Draws the mesh bounds in the Scene window in world space.
Only combine active GameObjects.
Only combine GameObjects that are marked as ‘Static’.
Use Search Box
Only combine meshes that are within the bounds of the search box.
Search Box Pivot/Size
The pivot position and the size of the search box.
Search box square
The first filter option is the search box, only GameObjects within this box will be combined. In the next update an automatic bound detection will be added, so it wouldn’t be necessary to use the search box.
Use Max Bounds Factor
Only include meshes which bounds are not bigger than x times the cell size. This option limits that too big objects are included which would make cell bounds too big for optimal culling.
User Vertex Input Limit
Only combine meshes that don’t exceed this vertex limit. MCS works best on small and medium meshes. Combining takes more memory than without, so having a good balance with only combining the necessary smaller meshes is important. I recommend to use a vertex input limit of around 5000. Unity’s static batching doesn’t have such filter option and it would all need to be selected manually to save memory, which can be tedious.
Use Vertex Input Limit LOD
Only combines meshes that have this vertex limit for all LODS, so if LOD0 has a higher vertex count than the limit the entire object won’t be included for combining. For LODs the limit can be higher somewhere between 10.000 – 15.000.
Only combine GameObjects which Layer is in this LayerMask.
Only combine GameObjects with this selected Tag.
Use Components Filter
Only combine GameObjects with a certain component. And: Only include GameObjects that have all components.\nOr: Include GameObjects that have one of the components.
Use Name Contains
Only combine GameObjects with a certain name (similar to windows explorer file search). E.g. can use Rocks*Green and will include all GameObjects that contain the word ‘Rocks’ and ‘Green’.
Combine cell based, only disable cells for combining parts for dynamic objects.
The size of the cells in which meshes will be combined into one mesh.
Offset position of the cells.
Remove Tris Below Surface
Remove triangles that are below any surface (terrain and/or meshes). This works collider based. This also removes vertices/normals/tangents/uvs, etc to save memory.
Surface Layer Mask
The layers on which the surface colliders are.
This needs to be at least the maximum height of your surface. This is the height where the rays are cast from.
Remove Backface Tris
Removes triangles that will never be visible for the camera from with a certain box volume. E.g. if you have an inner area where the player cannot go beyond and outside of this area you placed objects (even big mountain meshes) you can remove the back part of those meshes as the player will never see them. This can also work for a top down game or side scroller game where the player is never able to see a certain angle. This also removes vertices/normals/tangents/uvs, etc to save memory.
Box based: Case where Camera stays within the box volume.
Direction based: Case where Camera is orthogonal and doesn’t rotate.
The center and size of the box volume.
Two Sided Shadows
When using shadows this probably needs to be enabled to keep correct shadows, otherwise they will be cut-out because the backface triangles of the meshes are missing.
Add Mesh Colliders
Adds mesh colliders to the combined Meshes. Only use this options if you don’t have any colliders on the original GameObjects. It’s much faster to use primitive colliders on the original GameObjects. Can be a mix of primitive and mesh colliders, MCS will keep the original colliders and any other components working.
Make Meshes Unreadable
Removes the copy of the mesh arrays from CPU memory, which saves CPU memory. Only disable this option if you need to read from the meshes.
Use Vertex Output Limit
Limit the maximum vertices for combined meshes. This can be disabled.
Copy Baked Lighting
The Lighting of the original meshes will be copied to the combined meshes. Copy baked lighting can result in more combined meshes (more draw calls than with rebaking) as the source objects need to have the same lightmap index. The advantage is that the Scene file size doesn’t increase when used with ‘Combine In Runtime’.
Rebake the lighting on the combines meshes.
Scale in Lightmap
The scale of the combined meshes in the Lightmap, default value is 1 and a smaller value will create Lightmaps with less file size.
The combined GameObjects will be on this layer.
These are the settings for the multi-threaded (optional) combine job manager. There’s one global job manager that handles all combine jobs, and there can be many MeshCombineStudio prefabs which all send the jobs to the job manager. The job manager is designed to have as low memory and garbage allocation as possible. Each mesh type is only cached once and new combined mesh arrays are reused with pooling. I made a special plugin to have mesh array assigning alloc free by re-using the arrays pool.
Combine Job Mode
Combine At Once: Use this options if you quickly want to combine all meshes where FPS doesn’t matter. E.g. Just after loading a level.
Combine Per Frame: Choose the amount of meshes that will be combined per frame to keep FPS up. This can be used for any runtime editing like players creating levels, etc. A runtime API is still in the making for this and will be released soon.
Use Multi Threading
The combine part itself can be done on multiple threads. This can speed up the combining linearly with the amount of cores/threads available.
Use Main Thread
This option can be disabled when using multi threading. This will keep fps higher on the main thread. Still the assigning of the meshes can only be done on the main thread, since it needs to use the Unity API, which doesn’t allow any multi-threading. But the more compute intense combining itself can be done on the other threads.
Show the stats of the Job Manager. Amount of meshes cached, amount of pending jobs, etc.
Combine in Runtime
Combine meshes that meet the Search Option conditions in runtime.
Combine on Start
Combine meshes automatically on Start or call the CombineAll() method yourself from another script.
Original Mesh Renderers
What needs to be done with the original MeshRenders? (Disable or Delete).
What needs to be done with the orginal LOD Groups? (Disable or Delete).
Use Combine swap key
Switch between MCS and original GameObjects to see the performance difference.