12
\$\begingroup\$

I've an enemy, with this structure

  • Enemy
    • Body
      • Head
      • Arm Left
      • Arm right

And so on.

I also have a collider for each part of the body. In my "Enemy" object I've attached a script and in that script I would like to intercept possible collision (a bullet) for body, head, arm, left etc.

Is there a way to do this?

\$\endgroup\$
13
\$\begingroup\$

If you're using a Rigidbody with the character, you can get this out of the box. :)

So your hierarchy could look like this:

  • Character (has Rigidbody and control script)
    • child (maybe has colliders)
      • grandchild (maybe has colliders)

OnCollisionEnter messages will fire on the GameObject containing the Rigidbody, reaching your parent control script without needing to write an extra relay script to stick on each collider.

If you need to find out which of your child colliders was involved in the collision, you can do it like so:

void OnCollisionEnter(Collision collision) {
    Collider myCollider = collision.contacts[0].thisCollider;
    // Now do whatever you need with myCollider.
    // (If multiple colliders were involved in the collision, 
    // you can find them all by iterating through the contacts)
}
\$\endgroup\$
5
\$\begingroup\$

One way to solve this would be to have two scripts: one for the Enemy object and another one for the child(that you need to assign to the children of the Enemy obj)

Parent script

using UnityEngine;

 public class ParentScript : MonoBehaviour 
 {
     public void CollisionDetected(ChildScript childScript)
     {
         Debug.Log("child collided");
     } 
 }

Child script

using UnityEngine;

public class ChildScript : MonoBehaviour 
{
     void OnCollisionEnter(Collision collision)
     {
         transform.parent.GetComponent<ParentScript>().CollisionDetected(this);
     }
 }

This way you should get notified whenever a collision occurs to a child

\$\endgroup\$
  • 2
    \$\begingroup\$ If you use a solution like this and these collision happen a lot, I highly recommend having the children cache their receiving parent's GameObject. It's a good habit any time you're going to be calling the same GetComponent a lot and allows you to make any of the trickier "finding which parent up the chain to send to" logic only need to happen once. Also remember that transform.parent will only get the immediate parent. \$\endgroup\$ – Lunin Dec 3 '17 at 19:25
2
\$\begingroup\$

You can simply pass the top object to the children and call a function directly on it. This guarantees that you don't have to rely on parent propagation. So you don't end up doing silly things like transform.parent.parent

You could however automate this process with GetComponentInParent. This retrieves the first script it finds. Then cache that in your collision object, directly call functions on said cached object.

Alternatively you could make use of UnityEvents ( don't use Messages ) to bind functions to the child object. With unity events you can add any arbitrary listener so you can do more than just notify the top level object of the child object being hit.

\$\endgroup\$
1
\$\begingroup\$

Direct quote from Unity Answers (written by Ashish Dwivedi):

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.

\$\endgroup\$
1
\$\begingroup\$

You can perform a check on the collision and see which hit box was hit and also get the point of impact if needed.

note: the rigidbody is placed on the same object that has the Collision Check script.

This example is checking to see which hitbox the 'projectile' hit on a target.

private void OnCollisionEnter(Collision collision)
{                 
    if (collision.contacts[0].otherCollider.transform.gameObject.name == "HeadShot")                
       //DO STUFF            

    if (collision.contacts[0].otherCollider.transform.gameObject.name == "BodyShot")
       //DO STUFF    
}
\$\endgroup\$

protected by Vaillancourt Dec 4 '17 at 11:26

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.