- Home /
How to detect child object collisions on parent
Hi, I have a parent object with a rigidbody2D and a collider. In code I instantiate a second object from a prefab and make it a child of the first object. This child has a collider but no rigidbody. On the parent object I am using void OnCollisionEnter2D(Collision2D coll)
to detect collisions between the parent and other objects.
My problem is that this does not detect collisions that the child object has with other objects, it only catches those that directly collide with the parent's collider. The parent's OnCollisionEnter2D
doesn't run when the child hits something. Is there a way to catch child collisions as well without putting scripts on the child object?
Answer by Ashish Dwivedi · Feb 07, 2014 at 11:04 AM
Add a script to child and inside it have a reference of script of parent object. Now write 3 methods in parent script like ( OnCollisionEnter2DChild , OnCollisionStay2DChild , OnCollisionExit2DChild ) and called respective method from the methods (OnCollisionEnter2D , OnCollisionStay2D , OnCollisionExit2D) which are in child object script by passing the collision object.
Thanks. Out of curiosity does anyone know if we can achieve this differently, for example is it possible to modify colliders on the fly (e.g. modify the parent's collider to include the child's collider)?
You can add multiple colliders on the same object. I did this in 3D to have a better bounding volume with 2-3 box colliders on the same object. I guess you could dynamically add/remove/enable/disable some colliders. I don't know how to differentiate them though, I didn't need to, I guess you could keep a reference on each component if you instantiate them in script. Also, doing this, I receive multiple events: OnCollisionxxx is called for each collider of the object if something hits multiple colliders at the same time.
Answer by smacinn · Apr 27, 2014 at 02:25 AM
I ran into the same problem. It turns out that Rigidbody2D does not fire the OnCollision2D messages. A compound collider works for the physics aspects but not the messaging. Only the colliders fire the OnCollision message, and only to the monobehaviours that are on the same gameobject as the collider. The Collider2D does have a reference to the rigidbody so you can force the call up by placing this script on a child collider gameobject if you want the parent with the rigidbody to handle all the collision logic.
public class ChildCollider : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter2D( Collision2D collision) {
this.collider2D.attachedRigidbody.SendMessage("OnCollisionEnter2D",collision);
}
}
So it does look like a script is necessary but with this script you won't need to manually set the parent script as reference by dragging it onto a public variable, and this will also send the oncollision message to all Monobehaviours on the same gameobject as the RigidBody2D in case you have multiple scripts on the parent doing stuff when a collision happens.
Thanks @smacinn !
I was using compound colliders for both physics and trigger collisions and it wasn't obvious, at all, why that wasn't working.
Here's the 3D version with the updated Unity code for version 5.4 if anyone else is in need:
public class ChildCollider : $$anonymous$$onoBehaviour {
//Colliders only register a hit or collision when on the same level as rigidbody or parent. Compound Colliders need to be children. Solution is to add this code to all child colliders:
void OnCollisionEnter( Collision collision) {
this.GetComponent<Collider>().attachedRigidbody.Send$$anonymous$$essage("OnCollisionEnter",collision);
}
}
Answer by GameDevSA · Jun 26, 2017 at 02:47 AM
I have found a different solution that may be useful in some cases: http://bit.ly/2rS2hQB
That link talks about how in some cases, a child object can call the OnTrigger or OnCollision function of the parent. If your child is a trigger, like for attack hit boxes, this might be useful. I have found it is for me.
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "CrystalNode")
{
print("Hitting Crystal");
Damage(other.gameObject);
}
if (other.gameObject.tag == "OreNode")
{
print("Hitting Ore");
Damage(other.gameObject);
}
}
I have found that the above code being on the parent, correctly calls the correct print function depending on what the child trigger is overlapping. If your child had a rigid body, though, you may get weird physics behaviours, so this is probably best for triggers.
Note: I didn't notice this working initially when the child had no script attached. When I attached a script to my child and called OnTrigger, I noticed it working on the parent as well. I removed the script from the child and it continued calling on the parent. So, assuming it wasn't a bug, you don't need a script on the child at all.