Unidad: ¿cómo detectar la colisión que ocurre en un objeto hijo, desde un script principal?

12

Tengo un enemigo con esta estructura

  • Enemigo
    • Cuerpo
      • Cabeza
      • Brazo izquierdo
      • Brazo derecho

Y así.

También tengo un colisionador para cada parte del cuerpo. En mi objeto "Enemigo" he adjuntado un guión y en ese guión me gustaría interceptar una posible colisión (una bala) para cuerpo, cabeza, brazo, izquierda, etc.

¿Hay alguna forma de hacer esto?

fuerte
fuente

Respuestas:

16

Si estás usando un cuerpo rígido con el personaje, puedes sacarlo de la caja. :)

Entonces su jerarquía podría verse así:

  • Personaje (tiene Rigidbody y script de control)
    • niño (tal vez tiene colisionadores)
      • nieto (tal vez tiene colisionadores)

Los mensajes OnCollisionEnter se dispararán en el GameObject que contiene el Rigidbody, llegando a su script de control principal sin necesidad de escribir un script de retransmisión adicional para pegar en cada colisionador.

Si necesita averiguar cuál de los colisionadores de su hijo estuvo involucrado en la colisión, puede hacerlo así:

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
fuente
5

Una forma de resolver esto sería tener dos guiones: uno para el objeto Enemigo y otro para el niño (que debe asignar a los niños del obj Enemigo)

Script principal

using UnityEngine;

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

Guión hijo

using UnityEngine;

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

De esta manera, debe recibir una notificación cada vez que se produce una colisión con un niño


fuente
2
Si usa una solución como esta y estas colisiones ocurren mucho, le recomiendo que los niños guarden en caché el GameObject de sus padres receptores. Es un buen hábito cada vez que vas a llamar mucho al mismo GetComponent y te permite hacer que la lógica de "encontrar a qué padre de la cadena enviar" solo sea una vez. Recuerde también que transform.parent solo obtendrá el elemento primario inmediato .
Lunin
2

Simplemente puede pasar el objeto superior a los hijos y llamar a una función directamente sobre él. Esto garantiza que no tiene que depender de la propagación principal. Entonces no terminas haciendo cosas tontas comotransform.parent.parent

Sin embargo, podría automatizar este proceso con GetComponentInParent . Esto recupera el primer script que encuentra. Luego guarde en caché eso en su objeto de colisión, llame directamente a las funciones en dicho objeto en caché.

Alternativamente, puede hacer uso de UnityEvents (no use Messages) para vincular funciones al objeto secundario. Con los eventos de la unidad, puede agregar cualquier oyente arbitrario para que pueda hacer más que simplemente notificar al objeto de nivel superior del objeto secundario que está siendo golpeado.

Sidar
fuente
1

Cita directa de Unity Answers (escrito por Ashish Dwivedi ):

Agregue un script al elemento secundario y en su interior tenga una referencia del script del objeto primario. Ahora escriba 3 métodos en la secuencia de comandos principal como (OnCollisionEnter2DChild, OnCollisionStay2DChild, OnCollisionExit2DChild) y llame al método respectivo desde los métodos (OnCollisionEnter2D, OnCollisionStay2D, OnCollisionExit2D) que están en la secuencia de comandos del objeto secundario al pasar el objeto de colisión.

S. Tarık Çetin
fuente
1

Puede realizar una verificación de la colisión y ver qué caja de golpe se golpeó y también obtener el punto de impacto si es necesario.

nota: el cuerpo rígido se coloca en el mismo objeto que tiene la secuencia de comandos Collision Check.

Este ejemplo está comprobando para ver qué hitbox golpeó el 'proyectil' en un objetivo.

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
fuente