Search Unity

Any tricks to accessing the mesh of a batching static object?

Discussion in 'General Graphics' started by dgoyette, Jan 31, 2019.

  1. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Short version: Are there any clever ways to access the Mesh of an object marked as Batching Static?

    I realize I'm trying to do two things that are in direct competition with each other, but here's what I'm trying to do. I have various pieces of my level geometry that are generally 100% static, and I've been marking them as Batching static for rendering efficiency. I've recently added some behavior to display a particle effect on various objects, by using the "Mesh Renderer" setting of the particle system, and providing the object's mesh. Unfortunately, this doesn't work for Batching Static objects, as their mesh data is combined at runtime.

    I can untick Batching Static for these objects, but that seems really unfortunate. Most of the time, these objects are fully static, and only once in a while do I make use of this particle behavior. So it's frustrating to give up all the batching efficiency in order to add a feature like this.

    I was wondering if anyone had ideas on how I can keep the object flagged as Batching Static, but still somehow access its mesh data so I can pass that to the particle system? Or is it absolutely a one-or-the-other thing here?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    For Wayward Sky we used scripts with serialized mesh asset references rather than mesh renderer references. Alternatively you could make a copy of the game object & mesh render, and leave the game object disabled. Either way you need to pre-choose what meshes you want to be able to "receive" particles like this so Unity knows to keep around the original mesh.

    Unfortunately none of the other various rendering systems in Unity understand when a mesh renderer is using static batching. Unity internally understands what part of that combined mesh is that specific renderer component, but things like particle systems and DrawMeshRenderer functions do not.
     
    samizzo and dgoyette like this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    One other option is you could plausibly extract the mesh from the static mesh at runtime. I've not tried this method, but you could conceivably use a combination of MeshRenderer.isPartOfStaticBatch, MeshRenderer.subMeshStartIndex, and Mesh.GetTriangles() to extract the triangles & matching vertices of just the mesh you want and store it separately. If your MeshRenderer has multiple materials things might get a little trickier, but last I checked that was already buggy when used as a particle system's emission shape.
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Thanks, I'll see how it goes attaching the mesh asset to the script I'm using. I hadn't thought of that.
     
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    The approach of simply referencing the mesh asset worked fine. Ultimately my approach was:
    • Spawn the particle system and assign the mesh asset to the particle system's shape
    • Parent the particle system to the game object that holes the corresponding mesh renderer
    • Update the particle system's localPosition and localRotation to Vector3.zero, and localScale to Vector3.one. This causes the particle system to align properly to the visible mesh.
    This all works even when the renderer's are batching static, even in a build. Thanks again for setting me in the right direction.
     
    bgolus likes this.