Unity’s documentation doesn’t explain much about what flagging a game object as Batching Static actually does. For Occlusion Culling, Lightmaps, and NavMeshes it makes sense that those are baked at compile time; I’m guessing that moving a static object afterwards doesn’t regenerate any of those maps, so they’ll be incorrect. How does static batching get affected when you move a static object though? Does it force it to regenerate the batched geometry? Is this always slower than dynamic batching? If I create a new instance of a static prefab does it automatically get added to static batching? What if I destroy a static prefab? The documentation says things like “You can not change the transform of a static object” but I seem to be able to do it just fine; I’m just not sure what effect it’s having.
Static objects that are part of static batching get baked into a combo mesh in the build. So static batching will not work if static objects are moved.
–Eric
So does it just stop all static batching entirely as soon as you move one static object? Does adding a new static object have the same effect? Is there some sort of overhead when you move a static object, like does it need to delete the combined mesh and reload the individual meshes from disk? And how does StaticBatchingUtility.Combine interact with this? Does combine instantly combine the meshes and preserve the batch until you move a child?
I’m mostly trying to figure out how I should handle my game levels, which are almost entirely generated at runtime. If I procedurally place a bunch of rocks on my terrain while loading the level, should I mark those static and run Combine on them or is that a waste of time? If players can place walls in the environment, should those be static? I don’t really see much difference in performance on my own machine whether or not things are static, so I’m not sure what the best way to do this is. If an object mostly sits still and only is placed or removed occassionally, is it worth converting it to static and combining it or is it better to just leave everything dynamic?
An object can’t be moved once it’s combined. Or rather, you can move it, but the combined mesh will not be updated to reflect this.
Marking as static isn’t something you can do at runtime; that’s an editor thing. You just run Combine on the desired objects. Static batching reduces draw calls and doesn’t have the overhead that dynamic batching has, so it will always be faster than not having static batching. As to how much faster, you’d have to try it and see.
They can’t be, since as mentioned the static attribute doesn’t really exist at runtime.
As above, an object can’t be moved once it’s combined. Any dynamic objects should not be used with Combine.
–Eric
I was under the impression, from the docs, that objects could be moved and still statically batched by making them a child of a gameobject, and instead move that parent. Maybe I missunderstood?
" Once combined children can NOT change their Transform properties, howeverstaticBatchRoot can be moved."
http://docs.unity3d.com/Documentation/ScriptReference/StaticBatchingUtility.Combine.html
@bpears yes, you can statically batch at runtime a hierarchy of gameobjects that is moving all together (i.e., only the transform of the root is changed) by calling that function, which is a different process than marking it for static batching at build time in the Editor.
I see, so could this be done with several Root GameObjects? Or would a custom batching code need to be written? Or just the code snippet from the docs?
I wonder why Unity can manage this at runtime, and yet can’t manage static batching with actual GOs moving from their Roots. Seems silly.
I guess it would probably all work fine this way, as long as none of the batching groups are broken into 2 different Roots. Not sure how to go about having several different batches though. And this way you could drop far batch groups from memory and reload, maybe.
Is it possible to remove the combined mesh and reload its original mesh during runtime?
That’s what I’m sort of wondering too. I think so, but might have to write custom system, I don’t think Unity’s has much wiggle room, but I’m not sure.
advice from the gurus would be much appreciated!
Ok, here are some specific questions so, it’s not so broad. Using StaticBatchingUtility.Combine(); can the batched mesh be recalculated? If I were to enable/disable some of the inner meshes, or move the Root GameObject, calling this function would sort out the changes? Even if the individual meshes are moved instead of Root?
How can I set up multiple batches using this function? Will I just have to write an entirely new batching system?
I’ve learned a lot from this community, hope to learn more! Thank you
I don’t know answer to first question, as I haven’t used StaticBatchingUtility, but I’ll take a stab at rest.
Static batching combines all items marked as static into a single mesh, and individual objects meshes are not displayed. That’s why moving a static object will not update the display at runtime. The combined mesh contains two sets of data: visual mesh data like verbs, normals, etc., and an index set that can be used to tell GPU which vertices to display or cull.
I read that culling (frustum, occlusion) still culls individual objects that are part of a static group, and I confirmed this with LODGroups. I.e. Made a test with a bunch of trees in a scene, all marked as static, and gave each tree 2 LODs plus culling LOD. Despite being static, LOD meshes were switched and objects culled as necessary. Performance was great, so definitely still using a combined mesh. I also tested that I could deactivate an object, and it would be culled as well. So you can turn off/on static elements, but not move them as that would require an expensive recombining operation.
I would imagine all this applies to static meshes made with the utility as well. And just did a quick test to verify you can move the parent of combined objects, and they move correctly. And yes, you can have multiple static groups made with this utility. But I see no way to recombine after the initial combine…
I was able to change an object to static at runtime…
gameObject.isStatic = true;
and then proceded to place other non static GameObjects as children to it, which made them static too.
Note added emphasis above.
–Eric