Search Unity

physics collider not being used by BuildPhysicsWorld

Discussion in 'Physics for ECS' started by Conspiracy, Jan 14, 2020.

  1. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    So, I tried to create my own way to convert a mesh from a prefab to a physics collider mesh. I did this so I could instantiate an entity directly from script and not have to spawn a gameObject first. Also, I'm doing this as a test because I need this system to change entity's mesh collider in runtime with a script.

    The script did add a PhysicsCollider. However, the PhysicsCollider was not being used by the buildPhysicsWorld system and so it's basically not running.
    Code (CSharp):
    1. public class trackSpawner : MonoBehaviour
    2. {
    3.     private EntityManager EM;
    4.  
    5.     [SerializeField]
    6.     private float3 point;
    7.  
    8.     private float3[] verts;
    9.     private int3[] tris;
    10.  
    11.     private float vX;
    12.     private float vY;
    13.     private float vZ;
    14.  
    15.     // Start is called before the first frame update
    16.     void Awake()
    17.     {
    18.         EM = World.DefaultGameObjectInjectionWorld.EntityManager;
    19.     }
    20.  
    21.  
    22.     public void Spawn(GameObject obj, int totalAmount)
    23.     {
    24.         float3 sPoint = obj.GetComponent<track>().data.startPoint;
    25.         float3 ePoint = obj.GetComponent<track>().data.endPoint;
    26.  
    27.  
    28.         ///////////////////   /////////////   ///////////////////
    29.         ///////////////////   Get Mesh Data   ///////////////////
    30.         ///////////////////   /////////////   ///////////////////
    31.  
    32.         verts = new float3[obj.GetComponent<MeshFilter>().sharedMesh.vertices.Length];
    33.         tris = new int3[obj.GetComponent<MeshFilter>().sharedMesh.triangles.Length];
    34.  
    35.         for (int v = 0; v < obj.GetComponent<MeshFilter>().sharedMesh.vertices.Length; v++)
    36.         {
    37.             vX = obj.GetComponent<MeshFilter>().sharedMesh.vertices[v].x;
    38.             vY = obj.GetComponent<MeshFilter>().sharedMesh.vertices[v].y;
    39.             vZ = obj.GetComponent<MeshFilter>().sharedMesh.vertices[v].z;
    40.             verts[v] = new float3(vX, vY, vZ);
    41.  
    42.             Debug.Log(verts[v]);
    43.         }
    44.  
    45.         for (int t = 0; t < obj.GetComponent<MeshFilter>().sharedMesh.triangles.Length; t += 3)
    46.         {
    47.             tris[t] = new int3(
    48.                 obj.GetComponent<MeshFilter>().sharedMesh.triangles[t],
    49.                 obj.GetComponent<MeshFilter>().sharedMesh.triangles[t + 1],
    50.                 obj.GetComponent<MeshFilter>().sharedMesh.triangles[t + 2]);
    51.  
    52.             Debug.Log(tris[t]);
    53.         }
    54.  
    55.         NativeArray<float3> vertices = new NativeArray<float3>(verts, Allocator.Temp);
    56.         NativeArray<int3> triangles = new NativeArray<int3>(tris, Allocator.Temp);
    57.  
    58.         var filter = CollisionFilter.Default;
    59.         filter.BelongsTo = PhysicsCategoryTags.Everything.Value;
    60.         filter.CollidesWith = PhysicsCategoryTags.Everything.Value;
    61.         var material = Unity.Physics.Material.Default;
    62.         material.Flags = Unity.Physics.Material.MaterialFlags.EnableCollisionEvents;
    63.  
    64.         var colliderBlob = Unity.Physics.MeshCollider.Create(vertices, triangles, filter, material);
    65.         vertices.Dispose();
    66.         triangles.Dispose();
    67.  
    68.         // Create Entities
    69.         NativeArray<Entity> Tracks = new NativeArray<Entity>(totalAmount, Allocator.Temp);
    70.         EM.Instantiate(obj, Tracks);
    71.  
    72.         // set Data
    73.         for (int i = 0; i < Tracks.Length; i++)
    74.         {
    75.             EM.SetComponentData(Tracks[i], new Translation { Value = point - sPoint });
    76.             EM.AddComponentData(Tracks[i], new trackData { startPoint = sPoint, endPoint = ePoint });
    77.             EM.AddComponentData(Tracks[i], new PhysicsCollider { Value = colliderBlob });
    78.             EM.AddComponentData(Tracks[i], new PhysicsCustomTags { Value = 1 });
    79.             point += ePoint - sPoint;
    80.         }
    81.         Debug.Log("done");
    82.  
    83.         Tracks.Dispose();
    84.     }
    85. }
    am I missing something?
     
  2. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Can you elaborate on what you mean by the PhysicsCollider not being used by BuildPhysicsWorld? Are you not seeing any entities associated with that system? Are you seeing your instantiated entities in the Entity Debugger? Is there a Rotation component on the Entity?
    upload_2020-1-14_10-16-57.png
     
    Conspiracy likes this.
  3. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    Oh yeah, forgot to do that cuz I was tired whilst writing this thread but anyway
    zigzag.PNG track.PNG

    On the top Image is the entity I created using my code and on the bottom is the entity that was created using Convert to Entity script.
    As you can see, the entity with my code doesn't have any component that is being used by BuildPhysicsWorld

    why is that?
     
  4. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    "Is there a Rotation component on the Entity?" Oh wow, just added the rotation component to the entity. I didn't know I need to do that for it to work. Thank you
     
  5. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    Adding individual physics components may cause your implementations to break should a package update cause the physics systems to query for a different set of physics components. I think the proper way to avoid this is by having your Spawn method create a GO with Rigidbody, Collider, and custom authoring Monobehaviors, and then attach the ConvertToEntity authoring to that GO. The physics conversion system will then automatically add the components needed for the entity to be recognized by BuildPhysicsWorld. This would work even if the physics package were updated
     
  6. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    and that wouldn't cause a performance decrease?

    I don't really know much about how this all works because I'm more into the art/design side of gamedev but what happens to the GO when it gets converted and destroyed? (genuine question btw I'm not trying to be a smartass)

    cuz I need to repeatedly instantiate these entities and people say that repeatedly instantiating GO and destroying them is really bad for performance so.... is there any difference between destroying GO the usual way and with convertToEntity script?
     
  7. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    There's a system called GameObjectConversionSystem that searches for all GameObjects with ConvertToEntity. If it's marked as Convert and Destroy, the system first checks each of its Monobehaviors and figures out the ECS equivalent of them. Next, it takes all of these ECS equivalents, plus your own ECS components, and adds them to a newly created Entity. Once this is done, the original GameObject is destroyed. As for your use case there is a solution. Here's some starter code:

    Code (CSharp):
    1. [RequiresEntityConversion]
    2. public class StoredPrefabComponent : MonoBehaviour, IConvertGameObjectToEntity, IDeclareReferencedPrefabs
    3. {
    4.     [SerializeField]
    5.     private GameObject vantage;
    6.  
    7.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    8.     {
    9.         dstManager.AddComponentData(entity, new StoredPrefab
    10.         {
    11.             prefab = conversionSystem.GetPrimaryEntity(vantage),
    12.         });
    13.     }
    14.  
    15.     // the primary entity of the vantage GameObject is now a special prefab entity
    16.     public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
    17.     {
    18.         referencedPrefabs.Add(vantage);
    19.     }
    20. }
    Now you can query for StoredPrefab and access its prefab field to get the special prefab entity. This entity itself is not seen by any systems, but you can call EntityManager.Instantiate(prefabEntity) to create a normal entity instance of it which will be seen by systems. It's very fast and involves no garbage
     
    Conspiracy likes this.
  8. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    Thank you