Search Unity

Why is a MeshRenderer required for Convex Hulls? (including our workaround fix)

Discussion in 'Physics for ECS' started by Zec_, Mar 18, 2020.

  1. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    I'm working on a project where we're having a client and a server world, and for all prefabs converted to the server world we're removing all the MeshRenderers. This is causing an issue for us in that the convex hull conversion ignores all objects that doesn't have a MeshRenderer. I don't really see why this behaviour is desired, as the whole conversion more or less only is dependant on MeshFilters? We did however find a local solution to the problem, and I thought I should share it.

    In 0.3, the problematic code was moved to GetActiveChildrenScope.cs:
    public bool IsChildActiveAndBelongsToShape(T child, bool filterOutInvalid = true)
    {
    var meshFilter = (UnityComponent)child as MeshFilter;
    if (meshFilter != null)
    {
    if (meshFilter.sharedMesh == null)
    return false;
    var renderer = meshFilter.GetComponent<MeshRenderer>();
    if (renderer == null || !renderer.enabled) // Here's our problem.
    return false;

    The final row with the renderer check returns false for when either a renderer doesn't exist, or when it's disabled. This didn't work for us, as MeshRenderers didn't exist for our server conversion, and therefore the server didn't get proper converted convex hull shapes either. A solution would have been to set the custom mesh, but that would have meant that we would have to create custom meshes that joined together the child hierarchy of sub meshes.

    What we found was that the enabled check somewhat made sense if a MeshRenderer actually existed, but the behaviour of skipping the mesh when it didn't exist caused us issues. We made a local change to this, and changed it like this:
    if (renderer != null && !renderer.enabled)
    return false;

    This change made it so that if a disabled MeshRenderer exists, we ignore the shape. But if we only have a MeshFilter without a MeshRenderer, we're including it.

    I would like to ask if there's a better way of going about this, or if there's any plans to make it possible to convert convex hulls without MeshRenderer? I guess a good solution could be an option on the Physics Shape for ignoring the requirement to have MeshRenderers.
     
  2. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    You can assign a custom mesh if the collider type is set to ConvexHull or Mesh, and it will be used instead of searching the hierarchy for render geometry.
     

    Attached Files:

    Arnold_2013 likes this.
  3. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    Yes, I wrote about this in the previous post.
    What I see as the drawback with that is that we no longer can use the GameObject hierarchy of MeshFilters. We would either need to add a PhysicsShape to each child MeshFilter gameobject and make sure that all PhysicsShapes of children are configured in the same way, or we would need to create an actual custom mesh that represents the full child hierarchy.
     
  4. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Ok yes I understand, sorry. I think your proposal makes sense of only doing the enabled check if the renderer exists.
     
  5. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    (That said, I'm also curious: are you doing run-time conversion here, or are you using the DOTS Netcode workflows? I'm not acquainted with the details, but am pretty sure you can easily specify that rendering components are only used for the client configuration, so you just use the same source authoring data in both cases)
     
  6. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    I apologize for the lengthyness of this message, but it kind of feels like I needed to give a deeper explanation to shed some light on the questions you asked :)

    We're using Runtime conversion (for dynamic objects in the world) as well as SubScene converison (for the static world). We aren't really using the workflows from the DOTS Netcode (even if our actual netcode solution takes some inspiration from it).

    We're running a server world and a client world, and we have complete individual system setups for each world. As an example related to what we're talking about, we have removed the presentation group in our server world.

    The main area where the issue we're speaking about is caused is in our SubScenes. We've got a quite large world, separated into a bunch of SubScenes that we load on the server and the client.

    As the core implementation of SubScenes converts, stores and loads them as a single representation, we've made some tools to generate a server and a client SubScene based on a raw main SubScene. This means that we can store and load server subscenes that are stripped of client data, and client subscenes that are stripped of server data.

    We went with the solution to remove all MeshRenderers on the server subscene prior to conversion. The server doesn't need the rendering data, and as the resulting RenderMesh components are Shared Components, they cause objects with diverging rendering settings to not share ArchetypeChunks. The MeshRenderer conversion can also create a bunch of additional rendering entities based the configuration of it's submeshes. All those additional entities and components makes sense the client, but not on the server. Removing the RenderMesh shared component packs the objects better in memory.

    I guess we could add the PhysicsShape components during our server world generation step, which would solve our issue. I just posted this thread as I didn't really see the reason as to why MeshFilters wouldn't be included unless they had a MeshRenderer.
     
  7. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Why can you not use the sub-scene workflow for all of your content? If these dynamic objects are all just prefabs you are spawning at run-time then it is still the preferred workflow. (e.g., add a spawner script with GO prefab references to something in your sub-scene and use IDeclareReferencedPrefabs on it.) In general, all investment in the DOTS ecosystem is going to be toward sub-scene-based workflows, so run-time conversion may well be deprecated at some point.

    Really what I imagine you want is both representations to share the same source authoring data, so they won't fall out of sync (ala DOTS netcode workflows). So I think you want to basically create a copy of the converted client data during conversion with all the stuff your server doesn't need stripped out.

    The main reason I guess is that it is hard to heuristically reason about the intentionality of a MeshFilter without a MeshRenderer. It _could_ be there for a very specific reason, or it could be something someone accidentally forgot to remove, which might be hard to track down (especially if a primitive shape is fitted to it).
     
  8. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    Thank you for the detailed answer, really appreciated! I don't really have any follow-up questions, just thought I'd follow up on a couple of your questions:
    We can, and most likely will. We just haven't invested time into it yet. We really like the concept of subscenes, but we haven't really heard much about the future of it nor have anything happened with it since Entities 0.2. That has lead us to hesitate a bit lately regarding investing too much time into it at this stage. But we will most likely take that route in due time.

    It's an interesting thought for sure, but what I see as a potential issue with it is that the since all of it would be bundled in the same subscene, the subscene that contains the server data would become dependant on the art assets.

    We don't control the loading of assets for subscenes, so a headless server would have a ton of memory intensive art dependencies that it didn't have any use for.
     
  9. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    But it sounds like that is already the case, if you depend on meshes used by the art assets, right?

    The idea is that you strip this stuff out at conversion time. So the entity binary data that you load on the server only contains the subset of (run-time) components needed for simulation.
     
  10. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    I haven't investigated this enough, so I'm sorry to say that I can't answer for certain. I do however believe that we don't have any references to texture assets in our server subscenes, as the MeshRenderers are gone and therefore also the art reference to Materials and Meshes in the entity representation. I was also hoping that the Mesh references would be gone as well, as the Physics library doesn't directly need them unless we've used the CustomMesh option. The Convex hull option builds it's own mesh after all.

    We will need to investigate this further for sure, but I have seen that our serialized server subscenes are far smaller on disk than the serialized client subscenes.

    And that is why we haven't been keeping the client and server entities inside the same subscenes. Correct me if I'm wrong, but we can't load partial subscenes and we can't serialize one subscene as two separate binary representations. Therefore, we can't strip client data from the binary server subscene without actually having a separate server subscene.