Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question about the compatibility of LODs and static batching

Discussion in 'General Graphics' started by NUKKschocke, May 27, 2019.

  1. NUKKschocke

    NUKKschocke

    Joined:
    Oct 17, 2018
    Posts:
    34
    There have already been a few threads about this or a similar topic, but they all seem to glance over one aspect:
    Are having a renderer in an LODgroup and that renderer being marked as "batching static" incompatible?

    My case:
    I have hundreds of prefabs strewn across an area that use 4 different atlas materials and about 60 or so different models. (these are unmoving 3d scans of people used to make an area look "alive")
    These prefabs have LODs and are singular objects.
    What happens to the LODs (and their function) if I make all those objects statically batched?

    If I statically batch the objects and check on them in playmode, their MeshRenderers' meshes are replaced by the "combined meshes" as expected from batching.
    But a custom LOD-testing component I use to check if specific LODgroups work as expected stays locked at LOD2 (lowest) and the active tris/verts of every object I check stays at around 40k to 50k. This number would roughly be if all LOD2 meshes of these types of objects were combined.

    So my guess is that statically batching those objects breaks the LODs, breaks the frustum/occlusion culling capabilities of Unity and would lead to worse performance, even though the draw calls / batches would be reduced by it.

    Am I correct in this assumption?
     
    theforgot3n1 and Jonas-Neuston like this.
  2. NUKKschocke

    NUKKschocke

    Joined:
    Oct 17, 2018
    Posts:
    34
    Bump.

    This is basically a question about what will net more performance improvement. A lot of LODGroups on singular objects or a single massive combined mesh from all the identical meshes?
     
  3. NUKKschocke

    NUKKschocke

    Joined:
    Oct 17, 2018
    Posts:
    34
    Bump.

    Based on what aspects would a decision between using LODGroups and using static batching (or combining meshes) generally be made, anyway, when dealing with 200+ objects of the same mesh and material?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    The answer is there is no single answer. What will be most performant will depend on the scene and the hardware you're running on.

    Having LOD groups with static meshes is totally fine. If all of the LODs use the same material(s) Unity may even staticly batch different LODs together. The way Unity's static batching works is by combining meshes with the same material into a single giant mesh, but still renders each mesh renderer individually. Basically when rendering a mesh you can tell the GPU to only use a range of triangles rather than the whole mesh, and this is much, much faster to render. This means each mesh renderer component can be individually toggled on and off, including via LOD groups, but they cannot be moved.

    Manually combining multiple meshes into a single mesh on LOD swap is often referred to as HLOD, or hierarchical level of detail. When you have a lot of objects, it's a good alternative to basic per-object LOD since the cost of evaluating the LOD level and culling for every single object might end up eventually being more expensive than just rendering them in groups. Unity has a solution for that it released, along with utilities for automatically generating those LODs, here:
    https://blogs.unity3d.com/2018/01/1...ting-with-automatic-performance-improvements/

    One note of caution. The Github project they released makes use of Simplygon, which as far as I can tell is not actually available for Unity anymore. If you read the comments they also added support for some free mesh simplification tools. You could also skip all of that and just reuse the code they have to use your own meshes.
     
  5. NUKKschocke

    NUKKschocke

    Joined:
    Oct 17, 2018
    Posts:
    34
    Thank you for your reply. I'm in the throes of trying to salvage this mess of a project at the moment which is why I didn't check the thread for a while.
    If you have the time, I have a few follow-up questions (marked in bold).

    That's a given, of course. I've given a short description of my use case in my original post.

    Thank you very much. That is basically exactly what I was curious about.
    I feel like this should be mentioned somewhere in the documentation.

    And this means that I can basically statically batch every single non-animated prefab in the scene and the LODs would still function?
    I wonder if there is any additional overhead for using both optimization variations in tandem.

    I've stumbled upon that blog post a couple of months ago but time constraints and didn't allow for any testing of an implementation into our project. But thank you for reminding me.

    Is there any way to find out how large the overhead for the internal LOD-evaluation is? I don't remember seeing any calls to "CollectAllLODs" or "UpdateLODs" or similar in the profiler.

    Seems the Simplygon SDK and unitypackage still work with Unity 2018 versions but just aren't available from the asset store anymore. Thanks for the heads up!
     
    theforgot3n1 and Jonas-Neuston like this.
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Yes, the LODs would still function.

    Static batching & lighting uses more memory, but otherwise having static LODs vs non-static LODs are functionality identical for the rest of the system. The LOD system is calculating the approximate screen coverage of the mesh's bounds, and enabling / disabling the renderer accordingly. The code for all of that doesn't change between static and dynamic objects.

    It's hidden in the profiler someplace. Not sure where to be honest though. When it becomes a problem is when there are several thousands of objects, maybe tens or hundreds of thousands depending on your CPU. But if that's the case you're going to be having rendering problems long before that. This is also where instancing vs. static batching will make a lot more sense as static batching of tens of thousands of objects can potentially end up producing multiple gigabytes of static mesh data. When you have that many individual objects you're going to see the culling times go up way sooner than the LOD calculations since I think frustum and mask culling ends up being much more expensive than screen coverage approximations.
     
    theforgot3n1 and hungrybelome like this.
  7. NUKKschocke

    NUKKschocke

    Joined:
    Oct 17, 2018
    Posts:
    34
    Thank you very much. :)

    Am I reading this correctly? Because we have a directional light that can be rotated by user input, we are using Realtime Lighting exclusively.
    In that case, statically batching objects incurs an additional cost on lighting/shadow calculation?

    I don't have any actual numbers, but at a ballpark guess, we're looking at up to 40 LOD Objects in Detail Views and up to about a thousand (1000) objects in Camera Overview mode (seeing an entire area with buildings and trees) in the most taxing case.
    If I've read correctly, that amount of LOD Objects shouldn't be a problem and there's even some room left.

    Thank you again for your replies. You're basically providing me with a second voice to support my arguments in having to explain to people why the application's framerate is tanking. :)
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Static lighting, aka lightmaps, incurs an additional memory cost. Otherwise static batching alone offers the same render performance benefits to shadows as the main view.