Search Unity

How to assign a generated mesh to an entity and define its Physics Shape at runtime?

Discussion in 'Physics for ECS' started by ZzAtomiic, Feb 26, 2020.

  1. ZzAtomiic

    ZzAtomiic

    Joined:
    Mar 17, 2018
    Posts:
    6
    Hi!
    Basically what's in the title.
    I'm generating a mesh at runtime in a Component System (In its OnUpdate callback, because there's no way to create a mesh in a Job, right?), and I have the need to assign this mesh to a physics shape component (all the related components to have a working entity with physics) at runtime.
    Until now I can't see a way to do it. Can someone point me in the right direction?
    I'm using the following package versions:
    - Unity Physics: 0.2.5
    - Entities: 0.5.1-preview.11
    And I'm currently using: 2019.3.0f3 as Unity version.
    Thank you for any help!
     
  2. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I remember screenshotting this from someone else's code posted on this forum a while back:


    This shows how to replace a collider (including its geometry) within a job. Maybe you can take inspiration from it. Not sure if there are additional complexities for mesh colliders

    -------------

    Edit:
    I suppose you can do something like this:
    • myPhysicsCollider.Collider = MeshCollider.Create(verts, tris)
    But I'm not sure about the performance of it if you're updating it every frame. Looks like we'd need a "MeshCollider.Update(verts, tris)" as well for better efficiency
     
    Last edited: Feb 26, 2020
    heu3becteh likes this.
  3. ZzAtomiic

    ZzAtomiic

    Joined:
    Mar 17, 2018
    Posts:
    6
    Awesome!
    The code was slightly similar to what you posted, here is the pseudo-code to assign a MeshCollider to an Entity:

    Code (CSharp):
    1.  
    2. NativeArray<float3> meshVertices;
    3. NativeArray<int3> meshTris;
    4. using (meshTris = new NativeArray<int3>(generatedMesh.triangles.Length / 3, Allocator.Temp))
    5. using (meshVertices = new NativeArray<float3>(generatedMesh.vertices.Length, Allocator.Temp))
    6. {
    7.     int index = 0;
    8.     foreach (Vector3 v in generatedMesh.vertices)
    9.           meshVertices[index++] = v;
    10.  
    11.      index = 0;
    12.      for(int i = 0; i < generatedMesh.triangles.Length; i += 3)
    13.           meshTris[index++] = new int3(generatedMesh.triangles[i], generatedMesh.triangles[i + 1], generatedMesh.triangles[i + 2]);
    14.  
    15.      BlobAssetReference<Unity.Physics.Collider> meshColliderReference = Unity.Physics.MeshCollider.Create(meshVertices, meshTris, Unity.Physics.CollisionFilter.Default, Unity.Physics.Material.Default);
    16.      EntityManager.AddComponentData(entity, new Unity.Physics.PhysicsCollider() { Value = meshColliderReference });
    17. }
    18.  
    I didn't even see the
    Unity.Physics.MeshCollider.Create
    static overloads, my bad..
    Thank you again!
     
    heu3becteh, Krooq and roryo like this.
  4. roryo

    roryo

    Joined:
    May 21, 2009
    Posts:
    1,479
    @ZzAtomiic - this is super helpful! Thanks so much.

    Does anyone know if there is a more optimal way to create a Unity.Physics.MeshCollider from a Mesh?

    For example, I saw this: https://gist.github.com/LotteMakesStuff/c2f9b764b15f74d14c00ceb4214356b4

    Which uses a Vector3[] to NativeArray<float3> conversion function:

    Code (CSharp):
    1. unsafe NativeArray<float3> GetNativeVertexArrays(Vector3[] vertexArray)
    2.     {
    3.         // create a destination NativeArray to hold the vertices
    4.         NativeArray<float3> verts = new NativeArray<float3>(vertexArray.Length, Allocator.Persistent,
    5.             NativeArrayOptions.UninitializedMemory);
    6.  
    7.         // pin the mesh's vertex buffer in place...
    8.         fixed (void* vertexBufferPointer = vertexArray)
    9.         {
    10.             // ...and use memcpy to copy the Vector3[] into a NativeArray<floar3> without casting. whould be fast!
    11.             UnsafeUtility.MemCpy(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(verts),
    12.                 vertexBufferPointer, vertexArray.Length * (long) UnsafeUtility.SizeOf<float3>());
    13.         }
    14.         // we only hve to fix the .net array in place, the NativeArray is allocated in the C++ side of the engine and
    15.         // wont move arround unexpectedly. We have a pointer to it not a reference! thats basically what fixed does,
    16.         // we create a scope where its 'safe' to get a pointer and directly manipulate the array
    17.  
    18.         return verts;
    19.     }
    The reason I ask is that I am hoping to generate thousands of irregular meshes, all with MeshColliders. ;)
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,776
    @roryo mind, that using tons of different meshes in SCD, will cause entities, to be scattered across different chunks.
    Which may potentially lead, into loosing benefits of ECS.
     
    roryo likes this.