Search Unity

Converting collider cast to Job

Discussion in 'Physics for ECS' started by Janosgolya, Feb 1, 2020.

  1. Janosgolya

    Janosgolya

    Joined:
    Jul 19, 2012
    Posts:
    9
    I have a problem converting Main thread collider cast to job. I want to pass the results of the hit to "collide" component wich is used by other systems . I used this example code for main thread and it worked fine :

    https://docs.unity3d.com/Packages/com.unity.physics@0.2/manual/collision_queries.html

    .... but it's not very performant.

    Right now it gives me two errors

    InvalidOperationException: The native container has been declared as [WriteOnly] in the job, but you are reading from it.

    UnityException: ScheduleBatchedJobsAndComplete can only be called from the main thread.

    And I just don't understand what he want's me to do.
    I also dont know how to use the job example from above link, and it's not the Entities.ForEach one. Frankly it's hard for me to understand the old way to schedule jobs, I've just started to learn it the new way.


    Here is my code so far.

    Code (CSharp):
    1. using Unity.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using Unity.Mathematics;
    6. using Unity.Physics;
    7. using Unity.Transforms;
    8. using Collider = Unity.Physics.Collider;
    9. using Unity.Jobs;
    10. using Unity.Physics.Systems;
    11.  
    12.  
    13. public class PhysicsCollidingSystem : JobComponentSystem
    14.  
    15. {
    16.  
    17.  
    18.  
    19.     protected override unsafe JobHandle OnUpdate(JobHandle inputDeps)
    20.     {
    21.  
    22.  
    23.  
    24.         JobHandle jobHandle = Entities.ForEach((Entity entity, ref Translation translation, ref Rotation rotation, ref Collide collide, ref PhysicsVelocity velocityPh, ref Velocity velocity, ref Animation animation) =>
    25.         {
    26.  
    27.             EntityManager manager;
    28.  
    29.             manager = World.DefaultGameObjectInjectionWorld.EntityManager;
    30.  
    31.             BuildPhysicsWorld physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
    32.            
    33.             CollisionWorld collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
    34.  
    35.             Entity e = Entity.Null;
    36.  
    37.             Vector3 dir = new Vector3(0, 0, 0);
    38.  
    39.             if (animation.State == 1)
    40.             {
    41.                 dir = math.mul(rotation.Value, new Vector3(0, -0.04f, 0));
    42.  
    43.             }
    44.             else
    45.             {
    46.                 dir = math.mul(rotation.Value, new Vector3(0, 0, 0.05f));
    47.             }
    48.  
    49.             Vector3 translationValue = translation.Value;
    50.  
    51.  
    52.             //Debug.DrawRay(translation.Value, dir, Color.blue);
    53.  
    54.             if (collide.Value == false)
    55.             {
    56.  
    57.                 float3 collisionPosition = new float3(0, 0, 0);
    58.                 float3 collisionNormal = new float3(0, 0, 0);
    59.  
    60.                 //SphereCast(translation.Value, translationValue + dir, entity, out collisionNormal, out collisionPosition, out e);
    61.  
    62.                 float3 RayFrom = translation.Value;
    63.                 float3 RayTo = translationValue + dir;
    64.  
    65.  
    66.  
    67.                 //collisionNormal = float3.zero;
    68.                 //collisionPosition = float3.zero;
    69.                 e = Entity.Null;
    70.  
    71.                // Debug.DrawRay(RayFrom, RayTo, Color.green);
    72.  
    73.  
    74.                 var filter = new CollisionFilter()
    75.                 {
    76.                     BelongsTo = ~0u,
    77.                     CollidesWith = ~0u, // all 1s, so all layers, collide with everything
    78.                     GroupIndex = 0
    79.                 };
    80.  
    81.                 BlobAssetReference<Collider> sourceCollider = manager.GetComponentData<PhysicsCollider>(entity).Value;
    82.  
    83.  
    84.                 ColliderCastInput input = new ColliderCastInput()
    85.                 {
    86.                     Collider = (Collider*)sourceCollider.GetUnsafePtr(),
    87.                     Orientation = quaternion.identity,
    88.                     Start = RayFrom,
    89.                     End = RayTo
    90.                 };
    91.  
    92.  
    93.  
    94.                 ColliderCastHit hit = new ColliderCastHit();
    95.                 bool haveHit = collisionWorld.CastCollider(input, out hit);
    96.                 if (haveHit)
    97.                 {
    98.                     collisionPosition = hit.Position;
    99.                     collisionNormal = hit.SurfaceNormal;
    100.  
    101.  
    102.  
    103.                     e = physicsWorldSystem.PhysicsWorld.Bodies[hit.RigidBodyIndex].Entity;
    104.  
    105.                 }
    106.  
    107.  
    108.  
    109.                 if (e != Entity.Null)
    110.                 {
    111.  
    112.  
    113.                     collide.Value = true;
    114.  
    115.  
    116.                     collide.CollisionPos = collisionPosition;
    117.  
    118.                     collide.Normal = collisionNormal;
    119.  
    120.  
    121.                     //Debug.DrawRay(translation.Value, collisionNormal, Color.red, 10f);
    122.  
    123.  
    124.                 }
    125.  
    126.             }
    127.  
    128.         }).Schedule(inputDeps);
    129.         return jobHandle;
    130.     }
    131. }
     
  2. Janosgolya

    Janosgolya

    Joined:
    Jul 19, 2012
    Posts:
    9
    Modyfing it further down to cast rays, not colliders, I managed to get it down to one error:

    InvalidOperationException: The native container has been declared as [WriteOnly] in the job, but you are reading from it.

    And isolate it to this line of code:

    bool haveHit = collisionWorld.CastRay(input, out hit);


    I cannot mark it with [ReadOnly] as it does not compile.
    What am I missing here?


    Code (CSharp):
    1. protected override JobHandle OnUpdate(JobHandle inputDeps)
    2.     {
    3.  
    4.        
    5.  
    6.         JobHandle jobHandle = Entities.ForEach((Entity entity, ref Translation translation, ref Rotation rotation, ref Collide collide, ref PhysicsVelocity velocityPh, ref Velocity velocity, ref Animation animation) =>
    7.         {
    8.  
    9.  
    10.  
    11.  
    12.  
    13.             BuildPhysicsWorld physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
    14.  
    15.  
    16.            
    17.              CollisionWorld collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
    18.  
    19.  
    20.  
    21.             Entity e = Entity.Null;
    22.  
    23.            
    24.  
    25.             Vector3 dir = new Vector3(0, 0, 0);
    26.  
    27.             if (animation.State == 1)
    28.             {
    29.                 dir = math.mul(rotation.Value, new Vector3(0, -0.04f, 0));
    30.  
    31.             }
    32.             else
    33.             {
    34.                 dir = math.mul(rotation.Value, new Vector3(0, 0, 0.05f));
    35.             }
    36.  
    37.             Vector3 translationValue = translation.Value;
    38.  
    39.  
    40.             //Debug.DrawRay(translation.Value, dir, Color.blue);
    41.  
    42.             if (collide.Value == false)
    43.             {
    44.  
    45.                 float3 collisionPosition = new float3(0, 0, 0);
    46.                 float3 collisionNormal = new float3(0, 0, 0);
    47.  
    48.                 //SphereCast(translation.Value, translationValue + dir, entity, out collisionNormal, out collisionPosition, out e);
    49.  
    50.                 float3 RayFrom = translation.Value;
    51.                 float3 RayTo = translationValue + dir;
    52.  
    53.  
    54.  
    55.                 //collisionNormal = float3.zero;
    56.                 //collisionPosition = float3.zero;
    57.                 e = Entity.Null;
    58.  
    59.                 // Debug.DrawRay(RayFrom, RayTo, Color.green);
    60.  
    61.  
    62.                 var filter = new CollisionFilter()
    63.                 {
    64.                     BelongsTo = ~0u,
    65.                     CollidesWith = ~0u, // all 1s, so all layers, collide with everything
    66.                     GroupIndex = 0
    67.                 };
    68.  
    69.                 //BlobAssetReference<Collider> sourceCollider = manager.GetComponentData<PhysicsCollider>(entity).Value;
    70.  
    71.  
    72.                 RaycastInput input = new RaycastInput()
    73.                 {
    74.                     //Collider = (Collider*)sourceCollider.GetUnsafePtr(),
    75.                     //Orientation = quaternion.identity,
    76.                     Start = RayFrom,
    77.                     End = RayTo,
    78.                     Filter = filter
    79.                 };
    80.  
    81.  
    82.  
    83.  
    84.                 Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
    85.  
    86.  
    87.  
    88.                 bool haveHit = collisionWorld.CastRay(input, out hit);
    89.  
    90.                 //Debug.DrawRay(translation.Value, dir, Color.blue);
    91.                 if (haveHit)
    92.                 {
    93.                     collisionPosition = hit.Position;
    94.                     collisionNormal = hit.SurfaceNormal;
    95.  
    96.  
    97.  
    98.                     e = physicsWorldSystem.PhysicsWorld.Bodies[hit.RigidBodyIndex].Entity;
    99.  
    100.                 }
    101.  
    102.                
    103.  
    104.                 if (e != Entity.Null)
    105.                 {
    106.  
    107.  
    108.                     collide.Value = true;
    109.  
    110.  
    111.                     collide.CollisionPos = collisionPosition;
    112.  
    113.                     collide.Normal = collisionNormal;
    114.  
    115.  
    116.                     //Debug.DrawRay(translation.Value, collisionNormal, Color.red, 10f);
    117.  
    118.  
    119.                 }
    120.  
    121.                
    122.  
    123.             }
    124.  
    125.         }).Schedule(inputDeps);
    126.         return jobHandle;
    127.     }
    128. }
     
  3. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Can you try:
    1. Get reference to BuildPhysicsWorld outside the lambda
    2. use JobHandle.CombineDependencies(buildPhysicsWorld.FinalJobHandle, inputDeps)
    3. Pass the result to the Schedule() call
     
    Janosgolya likes this.