- Home /
How do you detect which child collider was hit?
Say you have a parent game object with a collider and rigidbody, and two children objects each with their own collider (but no script or rigidbody on each child). If you have a script on the parent with OnCollision/OnTrigger methods, how do you check to see which of the child colliders was hit when there's a collision?? I've seen this question asked about 10 different ways, and none of the questions have an answer.
I think this suggests it doesn't work that way. Have suggested in the past, using the OnCollision functions on the child objects themselves and feeding this information out to the parent with them.
I did what you suggested (using a script with OnCollision on child), the problem now is that the OnCollision gets triggered twice, on the child and on the parent. To prevent the duplicate OnCollision on the parent, I added a kinematic rigidbody to the child. But from what I've read having child rigidbodies in addition to the parent can cause problems. So I'm trying to find the correct solution.
Answer by Pangamini · Aug 27, 2019 at 01:56 PM
Just use collision.GetContacts(), each ContactPoint generated has both colliders accessible (thisCollider, otherCollider)
This should be the accepted answer, since it doesnt use tags. Tags should be avoided at all cost, since they often make up the last straw to identify things (quickly).
And then you can check the collision against an array of colliders that you can specify... Perfect answer! Exactly what I needed, thanks.
Answer by nems808 · Nov 20, 2019 at 11:08 PM
void OnCollisionEnter2D(Collision2D coll)
{
// Tag of the object this object collided with
Debug.Log(coll.collider.tag);
// Tag of the child of the parent object this script is attached to
Debug.Log("OTHER COLL " + coll.otherCollider.tag);
}
Answer by alxdncn · Feb 02, 2017 at 05:11 PM
Obviously quite a late answer, but just in case someone comes across this, in the current version of Unity you can look at Collision.collider.gameObject.name or .tag to see which collider was hit. Got the answer from Weston_2.
This doesn't answer the question! If I am a player with two children, one capsule collider and one box collider, and I run into a wall with my box collider, the Collision.collider.gameObject.name will return the WALL, not the box collider.
Answer by king_ · Aug 05, 2014 at 12:04 PM
nope it cannot be done i was having the same problem, you can achieve it if you attach script to every game object
Ya, I'm beco$$anonymous$$g convinced that this feature does not exist. So If I add a script to my child game objects that have their own collider, how do I prevent the OnCollision from triggering in the parent script also?
It can be done! Though this is old I thought if anyone reading needed it I'd add this straight from the manual.
public class ExampleClass : $$anonymous$$onoBehaviour {
void OnCollisionStay(Collision collision) {
foreach (ContactPoint contact in collision.contacts) {
print(contact.thisCollider.name + " hit " + contact.otherCollider.name);
Debug.DrawRay(contact.point, contact.normal, Color.white);
}
}
}
@Space$$anonymous$$anDan you're awesome! I was searching for ages for a solution and this is it. For anyone interested, here is a sample message for OnCollisionEnter which helps explain the process.
void OnCollisionEnter(Collision collision)
{
//$$anonymous$$y character is a parent player with two children, each of the children
//has a collider on. One child is tagged "Player_Head", the other is
//tagged "Player_Jacket" (you could also use cp.thisCollider.gameObject.name).
//As far as I know, collision.contacts is the only place where "thisCollider"
//can be found.
ContactPoint cp = collision.GetContacts(0); // edited as per Panga$$anonymous$$i's comment
if (cp.thisCollider.gameObject.tag == "Player_Jacket")
{
print("Jacket hit");
}
}
use GetContacts() ins$$anonymous$$d, the contacts property allocates garbage (it is even in the docs)
Thanks, have edited. You didn't really need the "even in the docs" comment though. We're trying to help each other out here, not make people feel stupid.
Answer by LSPressWorks · Aug 02, 2014 at 08:51 AM
The easiest way in my personal experience in unity is to add vars for the objects
**var child1 : Monobehavior**;//I think GameObject can work as well, but it more complicated
var child2 : MonoBehavior;
now assign them in the inspector.
Then add a public getter for a variable wasHit
in the child
var wasHit : int; //or bollean
function OnCollisionEnter(hitter : Collision)
{
this.wasHit ++;
}
public function wasHit() : int
{
**return this.wasHit;**
}
now from the original script you can do something like
var wasChild1HIt : int = child1.wasHit();
You're assigning that script as an object, saving a great deal of hassle with the usual marshaling crud. Other alternatives can include using a public static singleton class to store event states and trigger states(Honestly I do it a lot, since i used a home made toolkit in c++ so very much)This has a solid advantage in that you can always access more or less anythign by just doing this like,
wasChildHIt = Toolkit.wasChildHitGlobal;
but remember, the beauty of unity is that it gives WAY simple methods of doing this sort of thing, without really beating up your performance.
http://answers.unity3d.com/questions/15354/writing-functions-that-return-a-value.html http://answers.unity3d.com/questions/7555/how-do-i-call-a-function-in-another-gameobjects-sc.html
Thanks for taking the time to comment. While your suggestion helps, it doesn't answer my question. From what I've gathered from research, the ability to detect which child collider in a "compound collider" doesn't exist. :(
Your answer
Follow this Question
Related Questions
ignore child's collider 1 Answer
collision.gameObject returning parent. 1 Answer
Collider isn't working ? 2 Answers
Detect collision point?? 1 Answer
Trying to detect multiple points on a single collider 1 Answer