Baking Static Batches at Editor Time

Hi there, I’m currently working in an open world game with static content being streamed in and out of the scene as needed.

In order to improve FPS we started meddling with the StaticBatchingUtility.Combine whenever a chunk is loaded into scene, but the method is unfortunately too slow and reduce our FPS to a drag.

to improve that I tried to use the StaticBatchingUtility at editor time to bake the meshes and objects, but the resulting meshes have many layers of protection against saving (hideflags, meshes not readable, etc…)

Another possibility I’m researching is improving the StaticBatchingUtility speed or at least reduce the overhead by spreading out the batching across frames, but even batching 2 objects resulted into large FPS drops, I even got the method decompiled, but given that it uses UnityEngine internal namespace I cannot tamper with it unless I’m using reflection (which I also couldn’t get to work that well…)

tl;dr: is it possible to save meshes batched through StaticBatchingUtility.Combine / can I spread out the StaticBatchingUtility.Combine method through frames in order to reduce it’s overhead?

For whoever stumble into this thread.

tl;dr: StaticBatchingUtility.Combine();, set hideFlags to HideFlags.None for each Mesh and save assets.

I had to get around the useless protection Unity place on the meshes, so I’ve created an editor tool to instantiate all static objects, run StaticBatchingUtility.Combine(); based on their streaming pieces, then set hideFlags to HideFlags.None for each Mesh (not the renderers or filters, they are fine as they are) , create assets for each mesh and then create new prefabs for the batched ones, so that the designers can still edit the scene afterwards, but need to bake the static batching again…

Just in case it might help anyone else struggling with the performance of StaticBatchingUtility.Combine(), I have just discovered with my team that you should basically never, ever use Combine(GameObject staticBatchRoot), and should instead manually pass the game objects that you want to merge by using Combine(GameObject[] gos, GameObject staticBatchRoot). A quick look at the C# reference shows that for reasons I can’t understand, the former scans through all the game objects in the entire scene instead of iterating over the root’s children.

Doing this switch brought down the cost of batching from roughly 45 seconds to something like 3 seconds in some of our loading screens.

Did you ever figure this out? I need to do this for a map editor plugin that I’m working on.