Problems using RaycastCommand together with Jobs and some suggestions to it

Just a note m_UV contains the last 2 elements of the barycentricCoordinates. But it should contain the first 2 elements. Seems to be a bug. I don’t know if they are going to fix this as it is an non-public part of this struct. But on the otherhand what is the meaning of having it at all, when it contains wrong data.

With respect of DOTS/Burst/Jobs access to m_UV as a value type would be more than welcome!

Seems wrong, yes. But didn’t have time to check what you’re saying. Did you report a bug? :frowning:

Hey.

m_UV is precisely the barycentric coordinates as returned by the physics engine (see PhysX/physx/include/PxQueryReport.h at c3d5537bdebd6f5cd82fcaf87474b838fe6fd5fa · NVIDIAGameWorks/PhysX · GitHub).

However, what you get as RaycastHit.barycentricCoordinates is just a triplet that is defined here: UnityCsReference/Modules/Physics/ScriptBindings/Dynamics.bindings.cs at c84064be69f20dcf21ebe4a7bbc176d48e2f289c · Unity-Technologies/UnityCsReference · GitHub

That said, I understand the sentiment about being able to access the data of RaycastHit from threads, that should be doable and I’m adding a card to track this work for a future release.

Anthony.

1 Like

With 2021 changes its finally possible to get collider instance id. But at the same time there’s no way to get actually Collider for that id, since Object.FindObjectFromInstanceID is internal.

Wonder if reinterpreting custom structure of RaycastHit layout to RaycastHit, and then fetching collider property will do the trick. Maybe there’s a simpler way?

You cannot access managed classes in a job. It’s not thread-safe.

Yeah I know. I’ve got a case where results of raycasting comes from two separate sources - customly written trigger interactions, and Physx based queries. They’re gathered into single buffer and processed by systems. Some are managed and they run on main thread, here’s where getting actual collider is required.

I’d like to avoid storing whole RaycastHit struct, since its values aren’t used, and pretty much a waste of memory for this case (and data duplication, such as extra HitPoint, HitNormal, and HitDistance stored). Plus, its user error prone.

But without RaycastHit, there’s no way to fetch collider by instance id.

Then you already had your answer. :slight_smile: There’s no avoiding it.

I mean, there’s a special access for things like Transforms (TransformAccess). I guess conceivably it could be done for specific types like Collider/Collider2D but a collider is so much more than a simple Transform so it’d be very limited on what access you’d get. Thinking out loud!

1 Like

I need it in a managed context. In a system that runs on a main thread. No jobs done there.

1 Like

Ah right, given what you wrote I read it as also accessing the colliders off the main thread. Sorry, my misinterpretation!

Hmm, yeah, it’d be nice to expose that. It’d likely have to be UnityEngine.Object from which you can check the type and cast it or some such.

1 Like

That said, there’s nothing stopping the 2D/3D physics teams from exposing that somehow via the RaycastHit(2D) or Collider(2D) or Rigidbody(2D) types. I’ll ask “around”.

1 Like

Meanwhile, I’ve come up with this:

using System.Runtime.InteropServices;
using UnityEngine;

namespace HitsGathering {
   /// <summary>
   /// Hacked version of RaycastHit, allows to obtain collider by reinterpreting
   ///
   /// RaycastHitHack structure to RaycastHit and obtaining collider via property
   /// (since Object.FindObjectFromInstanceID is internal)
   ///
   /// TODO remove once exposed
   /// </summary>
   [StructLayout(LayoutKind.Sequential)]
   public struct RaycastHitHack {
      public Vector3 m_Point;
      public Vector3 m_Normal;
      public uint m_FaceID;
      public float m_Distance;
      public Vector2 m_UV;
      public int m_Collider;
   }

   public static class RaycastHitHackExt {
     public static Collider GetColliderByInstanceId(this int instanceId) {
         RaycastHitHack hack = new RaycastHitHack();
         hack.m_Collider = instanceId;

         unsafe {
            RaycastHit hit = *(RaycastHit*) &hack;
            Collider result = hit.collider;
#if DEBUG
            if (result != null) 
               Debug.Assert(instanceId == result.GetInstanceID());
#endif
            return result;
         }
      }
   }
}

Assert matches, and it seems to return correct colliders.
If anyone else stumbles upon it, works with 2021 - struct layout may vary based on the version used.

1 Like

Yes, I was going to suggest something like that but I didn’t have the guts. :slight_smile: Obviously it’s super prone to breaking.

1 Like

While we’re being crazy, the reflection route:

using UnityEngine;
using System.Reflection;

public class TestReflect : MonoBehaviour
{
    object[] instanceIDArg = new object[1];

    void Start()
    {
        instanceIDArg[0] = GetInstanceID();

        var DoesObjectWithInstanceIDExist = typeof(Object).GetMethod("DoesObjectWithInstanceIDExist", BindingFlags.Static | BindingFlags.NonPublic);
        if (DoesObjectWithInstanceIDExist != null)
        {
            var wasFound = (bool)DoesObjectWithInstanceIDExist.Invoke(null, instanceIDArg);
            if (wasFound)
            {
                Debug.Log("We found the object from its instance ID.");
            }
        }      

        var FindObjectFromInstanceID = typeof(Object).GetMethod("FindObjectFromInstanceID", BindingFlags.Static | BindingFlags.NonPublic);
        if (FindObjectFromInstanceID != null)
        {
            var foundObj = FindObjectFromInstanceID.Invoke(null, instanceIDArg);

            if (GetType() == foundObj.GetType())
            {
                Debug.Log("We found the object from its instance ID.");
            }
        }
    }
}
1 Like

For some reason GetHashCode() in Android builds does not actually resolve to instance id which trips the Assert.
Probably an intended behaviour (GetHashCode() gets patched or smth?) but in any case edited this to GetInstanceId() for safety reasons. Speed in ns does not matter in editor / debug environment anyway.

There is no documentation page for 2021.1 . I always look for stuff this way… Let me tell you why … Because searching for that easy change on the unity ChangeLog page is IMPOSSIBLE. (Please, please, make it easier to find changes related to X… better filters… etc)

So I guess it is only available on 2021.2+ ?

Could this help? https://alpha.release-notes.ds.unity3d.com/

1 Like

Being as you specifically tagged me in I have to tell you that I am not part of the 3D physics team nor would I have any way of implementing what you just asked for.

I have a problem using RaycastCommand on Objects with RidigBodys using Unity 2022.3.27f1.
When the target has a Rigidbody Component there are no Hit entries in the result array. I can reproduce it with a standard 3dCube. When I add a Rigidbody it is not hitting any more, vice versa if i remove the RigidBody it hits again. (took me a while to drill it down to that)
Any suggestions?

I think you should create a new thread. The title doesn’t fit your question.

Opend a new Thread: RaycastCommand not working with RigidBody - Unity Engine - Unity Discussions