Physics.SphereCastAll to get rigidbody's like OnCollisionEnter

Hi,
I want to use a Physics.SphereCastAll() to get all Gameobjects (Go’s) with a Rigidbody attached to it. But I only get dozent children of the needed Go’s .

What i currently do is:

RaycastHit[] hits = Physics.SphereCastAll(transform.position, 5, transform.forward, 1f, myLayerMask);
    
foreach (var hit in hits)
{
       Debug.Log(hit.collider.gameObject.name);
}

What should i do/use to get only the Go’s with rigidbody’s?

I cant iterate over the hits array. Because the rigidbody Go doen’t have a Collider. So i dont get this Go(s) by SphereCastAll.

And I can’t use

foreach (var hit in hits)
{
    hit.collider.transform.root.GetComponent<Rigidbody>()
}

because the Rigidbody is not on the root Transform.

I simply want to have a functionality like OnCollisionEnter() … this will only give the gameobject’s with a rigidbody. But for a point in the world.

I am not entirely understanding what your difficulty is but I will try. What is in that hits array is everything it detected, all the colliders. If you want to get the colliders (collider’s transform) that has a Rigidbody attached to it you can do exactly what you tried to do but instead of doing ‘root’ you can do like this:

     foreach (var hit in hits)
     {
         Rigidbody rb=   hit.collider.transform.GetComponentInChildren<Rigidbody>(true);
           Debug.Log(rb.gameObject);
         //true gives you even the ones that are disabled.
     }

This will give you all the GameObjects that have rigidbodies attached to it.

Yes that could do it. But is there no way to get the directly hitted Rigidbody’s like OnCollisionEnter() does? Another function like Physics.SphereCastAll eventually?

Thanks for your answer!

The physics system works with rigidbody object. A rigidbody actually performs the collision detection. Child colliders of a rigidbody belong to the parent rigidbody (known as compound collider). However SphereCastAll only looking for individual colliders. This has nothing to do with rigidbody physics. So you have to manually determine the corresponding rigidbody objects for each collider you’ve found.

First to get the corresponding Rigidbody of a collider you can use the relatively new GetComponentInParent. It is similar to GetComponentInChildren but the other way round. Instead of searching down the hierarchy it only searches upwards. Though just like GetComponentInChildren it will also search on the object itself. So if the object with the collider has a rigidbody attached, this rigidbody will be returned. If not it will check the parent until it reaches the top (root). The method will return null if there is no rigidbody anywhere in the hierarchy chain upwards.

If you only looking for rigidbodies you can filter out any colliders where GetComponentInParent returns null. For those where you get a rigidbody you would store those rigidbodies somewhere.

The next problem is if a rigidbody has several colliders, you will get the same rigidbody more than once (once for each collider that was found). So you have to filter out duplicates. This all can be easily done with Linq:

using System.Linq;

// [..]

RaycastHit[] hits = Physics.SphereCastAll(transform.position, 5, transform.forward, 1f, myLayerMask);
Rigidbody[] rbs = hits.Select(h=>h.collider.GetComponentInParent<Rigidbody>()).Where(r=>r!=null).Distinct().ToArray();

To break this down

hits.Select(h=>h.collider.GetComponentInParent<Rigidbody>()) will return an enumerable which gets the Rigidbody component for each element in hits. Of course as we said earlier this enumeration can contain null values as well as duplicate rigidbodies

.Where(r=>r!=null) creates a filtered enumerable and filters out the null entries. So we only have actual rigidbodies in our collection.

.Distinct() will create a new enumerable with all the duplicates removed. So it only contains distinct values.

Finally .ToArray() will turn the enumerable into an actual array of Rigidbodies. If you just need to iterate over this collection you don’t need to create an array. You can directly use the enumerable in a foreach loop. The return type of Distinct in out case is IEnumerable<Rigidbody>. However you may just use var like this

var rbs = hits.Select(h=>h.collider.GetComponentInParent<Rigidbody>()).Where(r=>r!=null).Distinct();
foreach(Rigidbody r in rbs)
{
    // do something with the rigidbody "r"
}