Jedność: jak wykryć kolizję na obiekcie podrzędnym ze skryptu nadrzędnego?


12

Mam wroga z tą strukturą

  • Wróg
    • Ciało
      • Głowa
      • Ramię w lewo
      • Ramię w prawo

I tak dalej.

Mam również zderzacz dla każdej części ciała. Do mojego obiektu „Wróg” załączyłem skrypt, w tym skrypcie chciałbym przechwycić możliwą kolizję (pocisk) ciała, głowy, ramienia, lewej itd.

Czy jest na to sposób?

Odpowiedzi:


16

Jeśli używasz Rigidbody z postacią, możesz wyciągnąć to z pudełka. :)

Twoja hierarchia może wyglądać następująco:

  • Postać (ma Sztywne ciało i skrypt sterujący)
    • dziecko (może ma zderzaki)
      • wnuk (może ma zderzaczy)

Wiadomości OnCollisionEnter będą uruchamiane na GameObject zawierającym Rigidbody, docierając do rodzica skryptu kontrolnego bez potrzeby pisania dodatkowego skryptu przekazywania, aby przykleić się do każdego zderzacza.

Jeśli chcesz dowiedzieć się, który z twoich dzieci zderzających się uczestniczył w kolizji, możesz to zrobić w następujący sposób:

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)
}

5

Jednym ze sposobów rozwiązania tego byłoby posiadanie dwóch skryptów: jeden dla obiektu Wróg i drugi dla dziecka (które należy przypisać do dzieci wroga obj)

Skrypt nadrzędny

using UnityEngine;

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

Skrypt potomny

using UnityEngine;

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

W ten sposób powinieneś otrzymywać powiadomienia za każdym razem, gdy nastąpi kolizja z dzieckiem


2
Jeśli użyjesz takiego rozwiązania, a te kolizje zdarzają się często, zdecydowanie polecam dzieciom buforowanie GameObject otrzymującego rodzica. Jest to dobry nawyk za każdym razem, gdy będziesz często dzwonić do tego samego GetComponent i pozwala ci dokonać trudniejszego „ustalenia, który z rodziców w łańcuchu, aby wysłać do” logiki, musi się zdarzyć tylko raz. Pamiętaj również, że transform.parent otrzyma tylko bezpośredniego rodzica.
Lunin,

2

Możesz po prostu przekazać górny obiekt dzieciom i wywołać funkcję bezpośrednio na nim. Gwarantuje to, że nie musisz polegać na propagacji rodziców. Więc nie robisz głupich rzeczytransform.parent.parent

Możesz jednak zautomatyzować ten proces za pomocą GetComponentInParent . Pobiera pierwszy znaleziony skrypt. Następnie buforuj to w swoim obiekcie kolizyjnym, bezpośrednio wywołuj funkcje na tym buforowanym obiekcie.

Alternatywnie możesz użyć UnityEvents (nie używaj Wiadomości) do powiązania funkcji z obiektem potomnym. Za pomocą zdarzeń jedności możesz dodać dowolny dowolny detektor, dzięki czemu możesz zrobić coś więcej niż tylko powiadomić obiekt najwyższego poziomu o trafieniu obiektu potomnego.


1

Bezpośredni cytat z Unity Answers (napisany przez Ashisha Dwivedi ):

Dodaj skrypt do dziecka, a wewnątrz niego znajduje się odwołanie do skryptu obiektu nadrzędnego. Teraz napisz 3 metody w skrypcie nadrzędnym, takie jak (OnCollisionEnter2DChild, OnCollisionStay2DChild, OnCollisionExit2DChild) i wywołaj odpowiednią metodę z metod (OnCollisionEnter2D, OnCollisionStay2D, OnCollisionExit2D), które są w skrypcie obiektu podrzędnego, przekazując obiekt kolizji.


1

Możesz sprawdzić kolizję i sprawdzić, które pole trafienia zostało trafione, a także w razie potrzeby uzyskać punkt uderzenia.

Uwaga: ciało sztywne jest umieszczane na tym samym obiekcie, który ma skrypt sprawdzania kolizji.

W tym przykładzie sprawdzono, który hitbox trafił „pocisk” w cel.

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    
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.