Unity: comment détecter une collision sur un objet enfant, à partir d'un script parent?

12

J'ai un ennemi, avec cette structure

  • Ennemi
    • Corps
      • Tête
      • Bras gauche
      • Bras droit

Etc.

J'ai aussi un collisionneur pour chaque partie du corps. Dans mon objet "Ennemi", j'ai attaché un script et dans ce script, j'aimerais intercepter une éventuelle collision (une balle) pour le corps, la tête, le bras, la gauche, etc.

Y a-t-il un moyen de faire cela?

lourd
la source

Réponses:

16

Si vous utilisez un Rigidbody avec le personnage, vous pouvez le retirer de la boîte. :)

Votre hiérarchie pourrait donc ressembler à ceci:

  • Personnage (a Rigidbody et script de contrôle)
    • enfant (a peut-être des collisionneurs)
      • petit-enfant (a peut-être des collisionneurs)

Les messages OnCollisionEnter se déclencheront sur le GameObject contenant le Rigidbody, atteignant votre script de contrôle parent sans avoir besoin d'écrire un script de relais supplémentaire à coller sur chaque collisionneur.

Si vous avez besoin de savoir lequel de vos enfants collisionneurs a été impliqué dans la collision, vous pouvez le faire comme suit:

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)
}
DMGregory
la source
5

Une façon de résoudre ce problème serait d'avoir deux scripts: un pour l'objet ennemi et un autre pour l'enfant (que vous devez attribuer aux enfants de l'obj ennemi)

Script parent

using UnityEngine;

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

Script enfant

using UnityEngine;

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

De cette façon, vous devriez être averti chaque fois qu'une collision survient avec un enfant


la source
2
Si vous utilisez une solution comme celle-ci et que ces collisions se produisent souvent, je recommande fortement aux enfants de mettre en cache le GameObject de leur parent récepteur. C'est une bonne habitude à chaque fois que vous appelez souvent le même GetComponent et vous permet de rendre plus difficile la recherche du parent de la chaîne à envoyer à la logique ne doit se produire qu'une seule fois. Souvenez-vous également que transform.parent n'obtiendra que le parent immédiat .
Lunin
2

Vous pouvez simplement passer l'objet supérieur aux enfants et appeler une fonction directement dessus. Cela garantit que vous n'avez pas à vous fier à la propagation parent. Donc vous ne finissez pas par faire des bêtises commetransform.parent.parent

Vous pouvez cependant automatiser ce processus avec GetComponentInParent . Cela récupère le premier script qu'il trouve. Mettez ensuite cela en cache dans votre objet de collision, appelez directement des fonctions sur ledit objet mis en cache.

Vous pouvez également utiliser UnityEvents (ne pas utiliser de messages) pour lier des fonctions à l'objet enfant. Avec les événements d'unité, vous pouvez ajouter n'importe quel écouteur arbitraire afin que vous puissiez faire plus que simplement notifier l'objet de niveau supérieur de l'objet enfant touché.

Sidar
la source
1

Citation directe de Unity Answers (écrite par Ashish Dwivedi ):

Ajoutez un script à l'enfant et à l'intérieur il a une référence de script de l'objet parent. Maintenant, écrivez 3 méthodes dans le script parent comme (OnCollisionEnter2DChild, OnCollisionStay2DChild, OnCollisionExit2DChild) et appelez la méthode respective à partir des méthodes (OnCollisionEnter2D, OnCollisionStay2D, OnCollisionExit2D) qui sont dans le script d'objet enfant en passant l'objet collision.

S. Tarık Çetin
la source
1

Vous pouvez effectuer une vérification de la collision et voir quelle case a été touchée et obtenir le point d'impact si nécessaire.

remarque: le corps rigide est placé sur le même objet que le script Collision Check.

Cet exemple vérifie pour voir quelle hitbox le «projectile» a frappé sur une cible.

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    
}
Justin Markwell
la source