- Home /
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.
Answer by FlightOfOne · Oct 12, 2018 at 01:13 AM
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.
Answer by Baumkuchen · Oct 12, 2018 at 09:23 AM
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!
OntriggerEnter and OnCollisionEnter do not detect Rigidbodies. It seems that way because ONE of the interacting (e.g the player and a box) objects is REQUIRED to have a rigidbody attached to it, but not both. OnCollision detects the collider, just like the spherecast, no difference. Rigidbodies do not receive hits, it just supports physics aspects of the hit check in Collision. Short answer is no, there's no built in way to find rigidbodies by casting a hit check. What exactly are you trying to accomplish here? $$anonymous$$aybe there is a more efficient way.
Answer by Bunny83 · Oct 12, 2018 at 01:52 PM
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"
}
Your answer
Follow this Question
Related Questions
OnCollisionEnter getting child instead 0 Answers
Mesh renderer does not move with parent rigid body 5 Answers
Unity creating static colliders 1 Answer
Get all child not working? 1 Answer
Detect collision point?? 1 Answer