Search Unity

can't work with RaycastCommand results in jobs?

Discussion in 'Entity Component System' started by Baste, Jun 20, 2018.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    I'm trying to do some raycasting in jobs, but I've hit a snag. The
    RaycastCommand.ScheduleBatch stuff works great, and I can do a ton of raycasts in parallel. The results of the commands are just the RaycastHits, and you're supposed to check if the colliders are null to see if something's been hit or not.

    Problem is, you can't check if the results are null or not in a job. Here's a very simplified example, where I'm trying to write 1 if the raycast hit something, and 0 if it didn't:

    Code (csharp):
    1. private struct CanSeeJob : IJobParallelFor {
    2.     [ReadOnly]
    3.     public NativeArray<RaycastHit> lineOfSightResults;
    4.  
    5.     public NativeArray<int> canSee;
    6.  
    7.     public void Execute(int index) {
    8.         bool sightClear = lineOfSightResults[index].collider == null;
    9.         canSee[index] = sightClear ? 1 : 0;
    10.     }
    11. }
    And the result is:

    This problem is compounded by the fact that I'm not really interested in the collider that was hit - I'm just interested in if there was a hit at all. I could transfer the result on the main thread, but that would slow down things a lot. Any ideas?

    Right now I've got a hack:
    Code (csharp):
    1. bool sightClear = lineOfSightResults[index].point == default(Vector3);
    but that does not feel good.
    Am I missing something? Is there some better way to work with raycasts in jobs?


    If this isn't supported now, I think you could modify RaycastHit to contain information about if something was hit or not without adding any overhead. From looking at this, I'm pretty sure you could have something like:

    Code (csharp):
    1. public bool HitAnything { get { return m_Collider != 0; } }
    Assuming that m_Collider isn't set when nothing is hit.
     
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Ya I brought up a similar issue asking for the layer to be added to RaycastHit, as masks alone can't always suffice.

    I'm wondering if internally they just don't have an easy way to access the collider. RaycastCommand could for example be taking a much more direct path then other raycast api's, unable itself to access stuff on the main thread without changes to other code.
     
  3. VildNinja

    VildNinja

    Joined:
    Jan 17, 2013
    Posts:
    8
    I have a nasty unsafe workaround to get the underlying values. I've created an exposed version of RaycastHit:
    Code (CSharp):
    1. private struct ExposedHit
    2. {
    3.     // MUST BE EXACT MATCH WITH RaycastHit!!
    4.     // - used for unsafe casting
    5.     public Vector3 m_Point;
    6.     public Vector3 m_Normal;
    7.     public int m_FaceID;
    8.     public float m_Distance;
    9.     public Vector2 m_UV;
    10.     public int m_Collider;
    11. }
    and do a pointer cast from the original RaycastHit to copy over the data:
    Code (CSharp):
    1. var eHit = *((ExposedHit*)&hit);
    2. if (eHit.m_Collider == 0)
    3.     // no hit
    that way I can dirrectly check if m_Collider == 0

    Edit: On startup I do a sizeof check to verify they still match (this is not 100% accurate, but we are not gonna ship with this hack regardless)
    Code (CSharp):
    1. if (sizeof(RaycastHit) != sizeof(ExposedHit))
    2.     throw new Exception("RaycastHit changed! - tell Jannek");
    Edit2: With native slices you can do the conversion when you pass the data to the job instead:
    Code (CSharp):
    1. hits.Slice(0, rays.Length).SliceConvert<ExposedHit>()
     
    Last edited: Nov 23, 2018
    Ghat-Smith and SimonCVintecc like this.
  4. RaL

    RaL

    Joined:
    Nov 29, 2013
    Posts:
    35
    I would just check if hit.distance > 0
     
    xVergilx, zhuchun, Nothke and 2 others like this.
  5. rohan_zatun

    rohan_zatun

    Joined:
    Aug 18, 2021
    Posts:
    6
    Does this still work?