Search Unity

Casting one collider with another of a ITriggerEventsJob pair

Discussion in 'Physics for ECS' started by Jawsarn, Jun 4, 2020.

  1. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    245
    So I'm trying to find the point of contact in a Trigger job, so far it only seem to work between some entities. I've tried Raycast, changing the collider to be used directly from PhysicsCollider component. I can see that it enters the if statement of fetching the leaf, but only enters the if statement for the colliderCast if it hits the ground mesh. If it's hitting my entity with a trigger and normal collider (mind I've also tried removing any of these) it never enters.

    Code (CSharp):
    1.         [BurstCompile]
    2.         struct TriggerHitJob : ITriggerEventsJob
    3.         {
    4.             [ReadOnly]
    5.             public ComponentDataFromEntity<ProjectileData> projectileDataFromEntity;
    6.  
    7.             public BufferFromEntity<DamageHitDataElement> projectileHitFromEntity;
    8.  
    9.             [ReadOnly]
    10.             public ComponentDataFromEntity<DamageVisualData> damageVisualDataFromEntity;
    11.  
    12.             [ReadOnly]
    13.             public ComponentDataFromEntity<Translation> transFromEntity;
    14.            
    15.             [ReadOnly]
    16.             public ComponentDataFromEntity<Rotation> rotFromEntity;
    17.  
    18.             [ReadOnly]
    19.             public ComponentDataFromEntity<PhysicsCollider> physicscolliderFromEntity;
    20.            
    21.             [ReadOnly]
    22.             public ComponentDataFromEntity<PhysicsVelocity> physicsVelocityFromEntity;
    23.            
    24.             public uint tick;
    25.  
    26.             [ReadOnly] public PhysicsWorld world;
    27.  
    28.             public uint shieldFilterValue;
    29.  
    30.             public float deltaTime;
    31.  
    32.             public void Execute(TriggerEvent triggerEvent)
    33.             {
    34.                 Entity entityA = triggerEvent.Entities.EntityA;
    35.                 Entity entityB = triggerEvent.Entities.EntityB;
    36.  
    37.                 bool isBodyAProjectile = projectileHitFromEntity.Exists(entityA);
    38.                 bool isBodyBProjectile = projectileHitFromEntity.Exists(entityB);
    39.  
    40.                 // Ignoring projectiles overlapping other projectiles for now
    41.                 if (isBodyAProjectile == isBodyBProjectile)
    42.                     return;
    43.  
    44.                 var projectileEntity = isBodyAProjectile ? entityA : entityB;
    45.                 var hitEntity = isBodyAProjectile ? entityB : entityA;
    46.  
    47.                 var projectileData = projectileDataFromEntity[projectileEntity];
    48.                 var visualEffectData = damageVisualDataFromEntity[projectileEntity];
    49.  
    50.                 // If we already exploded
    51.                 if (visualEffectData.visualEffectTick != 0)
    52.                 {
    53.                     return;
    54.                 }
    55.  
    56.                 // Disable self hit
    57.                 if (hitEntity == projectileData.ownerEntity)
    58.                 {
    59.                     return;
    60.                 }
    61.  
    62.                 var body = isBodyAProjectile ? triggerEvent.BodyIndices.BodyBIndex : triggerEvent.BodyIndices.BodyAIndex;
    63.                 var key = isBodyAProjectile ? triggerEvent.ColliderKeys.ColliderKeyB : triggerEvent.ColliderKeys.ColliderKeyA;
    64.                 var trans = transFromEntity[projectileEntity];
    65.                 var rot = rotFromEntity[projectileEntity];
    66.  
    67.                 var hitPos = trans.Value;
    68.                 bool isShield = false;
    69.                 bool hitBySecondRaycast = false;
    70.  
    71.                 if (world.Bodies[body].Collider.Value.GetLeaf(key, out ChildCollider leaf))
    72.                 {
    73.                     unsafe
    74.                     {
    75.                         // I get here
    76.                         isShield = leaf.Collider->Filter.BelongsTo == shieldFilterValue;
    77.  
    78.                         var colliderCastInput = new ColliderCastInput()
    79.                         {
    80.                             End = trans.Value + deltaTime * physicsVelocityFromEntity[projectileEntity].Linear*1.2f,
    81.                             Start = trans.Value - deltaTime * physicsVelocityFromEntity[projectileEntity].Linear *1.2f,
    82.                             Collider = physicscolliderFromEntity[projectileEntity].ColliderPtr,
    83.                             Orientation = rot.Value
    84.                         };
    85.  
    86.                         if (leaf.Collider->CastCollider(colliderCastInput, out ColliderCastHit closestHit))
    87.                         {
    88.                             // Never enters on things with shields(two colliders)
    89.                             hitPos = closestHit.Position;
    90.                             hitBySecondRaycast = true;
    91.                         }
    92.                     }
    93.                 }
    94.                
    95.                 var buffer = projectileHitFromEntity[projectileEntity];
    96.                
    97.                 buffer.Add(new DamageHitDataElement()
    98.                 {
    99.                     hitEntity = hitEntity,
    100.                     hitPos = hitPos,
    101.                     isShield = isShield,
    102.                     frameDistance = math.length(trans.Value - hitPos),
    103.                     hitBySecondRaycast = hitBySecondRaycast,
    104.                 });
    105.             }
    106.         }
     
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    From what I can see, your query input is in world space, while if you want to query directly on collider the input needs to be in that collider's space. So you need to put your start and end into collider space, as well as orientation, and when getting the output back it will also be in collider space, so you need to do the inverse to get it in world space.
     
    Jawsarn likes this.
  3. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    245
    Thanks a lot! I almost considered it, but thought that the collider would be somehow connected to its position, but it makes sense. Most of my hits are registered correct now, but when I hit at the edge of the collider it seems that it misses. (both are spheres) So I guess this would be some floating precision error? But it seems to be very easy to reproduce so I'm not 100%.
     
  4. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    I think ray cast could definitely miss if hitting exactly on the edge, I've seen that for sure. If not float precision, could be related to Bevel Radius and maybe you are hitting the "inflated" area of the shape. Try setting it to 0, although I wouldn't recommend doing that in your simulation, just to verify that that's what happens.
     
  5. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    245
    Hey, thanks for the suggestion. But I'm using sphere colliders on both sides, and don't think they have Bevel Radius right?

    Haven't looked into it too much more, but this is the current code;

    Code (CSharp):
    1.         [BurstCompile]
    2.         struct TriggerHitJob : ITriggerEventsJob
    3.         {
    4.             [ReadOnly]
    5.             public ComponentDataFromEntity<ProjectileData> projectileDataFromEntity;
    6.  
    7.             public BufferFromEntity<DamageHitDataElement> projectileHitFromEntity;
    8.  
    9.             [ReadOnly]
    10.             public ComponentDataFromEntity<DamageVisualData> damageVisualDataFromEntity;
    11.  
    12.             [ReadOnly]
    13.             public ComponentDataFromEntity<Translation> transFromEntity;
    14.            
    15.             [ReadOnly]
    16.             public ComponentDataFromEntity<Rotation> rotFromEntity;
    17.  
    18.             [ReadOnly]
    19.             public ComponentDataFromEntity<LocalToWorld> ltwFromEntity;
    20.            
    21.             [ReadOnly]
    22.             public ComponentDataFromEntity<PhysicsCollider> physicscolliderFromEntity;
    23.            
    24.             [ReadOnly]
    25.             public ComponentDataFromEntity<PhysicsVelocity> physicsVelocityFromEntity;
    26.            
    27.             public uint tick;
    28.  
    29.             [ReadOnly] public PhysicsWorld world;
    30.  
    31.             public uint shieldFilterValue;
    32.  
    33.             public float deltaTime;
    34.  
    35.             public void Execute(TriggerEvent triggerEvent)
    36.             {
    37.                 Entity entityA = triggerEvent.Entities.EntityA;
    38.                 Entity entityB = triggerEvent.Entities.EntityB;
    39.  
    40.                 bool isBodyAProjectile = projectileHitFromEntity.Exists(entityA);
    41.                 bool isBodyBProjectile = projectileHitFromEntity.Exists(entityB);
    42.  
    43.                 // Ignoring projectiles overlapping other projectiles for now
    44.                 if (isBodyAProjectile == isBodyBProjectile)
    45.                     return;
    46.  
    47.                 var projectileEntity = isBodyAProjectile ? entityA : entityB;
    48.                 var hitEntity = isBodyAProjectile ? entityB : entityA;
    49.  
    50.                 var projectileData = projectileDataFromEntity[projectileEntity];
    51.                 var visualEffectData = damageVisualDataFromEntity[projectileEntity];
    52.  
    53.                 // If we already exploded
    54.                 if (visualEffectData.visualEffectTick != 0)
    55.                 {
    56.                     return;
    57.                 }
    58.  
    59.                 // Disable self hit
    60.                 if (hitEntity == projectileData.ownerEntity)
    61.                 {
    62.                     return;
    63.                 }
    64.  
    65.                 var body = isBodyAProjectile ? triggerEvent.BodyIndices.BodyBIndex : triggerEvent.BodyIndices.BodyAIndex;
    66.                 var key = isBodyAProjectile ? triggerEvent.ColliderKeys.ColliderKeyB : triggerEvent.ColliderKeys.ColliderKeyA;
    67.                 var trans = transFromEntity[projectileEntity];
    68.                 var rot = rotFromEntity[projectileEntity];
    69.  
    70.                 var hitPos = trans.Value;
    71.                 bool isShield = false;
    72.                 bool hitBySecondRaycast = false;
    73.                 var pos = float3.zero;
    74.                 var posLeaf = float3.zero;
    75.                 if (world.Bodies[body].Collider.Value.GetLeaf(key, out ChildCollider leaf))
    76.                 {
    77.                     unsafe
    78.                     {
    79.                         // I get here
    80.                         isShield = leaf.Collider->Filter.BelongsTo == shieldFilterValue;
    81.  
    82.                         var ltw = ltwFromEntity[hitEntity];
    83.                         var ltwInv = math.inverse(ltw.Value);
    84.                         var start = math.mul(ltwInv, new float4(trans.Value - deltaTime * physicsVelocityFromEntity[projectileEntity].Linear * 1.2f, 1.0f)).xyz;
    85.                         var end = math.mul(ltwInv, new float4(trans.Value + + deltaTime * physicsVelocityFromEntity[projectileEntity].Linear * 1.2f, 1.0f)).xyz; // TODO fix
    86.                         var orientation = math.mul(math.inverse(ltw.Rotation), rot.Value);
    87.                        
    88.                         var colliderCastInput = new ColliderCastInput()
    89.                         {
    90.                             End = end,
    91.                             Start = start,
    92.                             Collider = physicscolliderFromEntity[projectileEntity].ColliderPtr,
    93.                             Orientation = rot.Value
    94.                         };
    95.  
    96.  
    97.                         posLeaf = world.Bodies[body].WorldFromBody.pos;
    98.                         pos = ltw.Position;
    99.                         if (leaf.Collider->CastCollider(colliderCastInput, out ColliderCastHit closestHit))
    100.                         {
    101.                             // Never enters on things with shields(two colliders)
    102.                             hitPos = math.mul(ltw.Value, new float4(closestHit.Position,1.0f)).xyz;
    103.                             hitBySecondRaycast = true;
    104.                         }
    105.                     }
    106.                 }
    107.                
    108.                 var buffer = projectileHitFromEntity[projectileEntity];
    109.                
    110.                 buffer.Add(new DamageHitDataElement()
    111.                 {
    112.                     hitEntity = hitEntity,
    113.                     hitPos = hitPos,
    114.                     isShield = isShield,
    115.                     frameDistance = math.length(trans.Value - hitPos),
    116.                     hitBySecondRaycast = hitBySecondRaycast,
    117.                 });
    118.             }
    119.         }
     
  6. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Yeah you are right, bevel radius of the sphere is irrelevant... Then it's most likely the float precision you are seeing... Anything else looking wrong other than these edge cases?