Unity: как обнаружить столкновение на дочернем объекте из родительского скрипта?


12

У меня есть враг с этой структурой

  • враг
    • тело
      • Глава
      • Рука левая
      • Правая рука

И так далее.

У меня также есть коллайдер для каждой части тела. В моем объекте «Враг» я прикрепил сценарий, и в этом сценарии я хотел бы перехватить возможное столкновение (пулю) для тела, головы, руки, левой стороны и т. Д.

Есть ли способ сделать это?

Ответы:


16

Если вы используете Rigidbody с персонажем, вы можете получить это из коробки. :)

Итак, ваша иерархия может выглядеть так:

  • Персонаж (имеет Rigidbody и управляющий скрипт)
    • ребенок (может быть, есть коллайдеры)
      • внук (может быть, есть коллайдеры)

Сообщения OnCollisionEnter будут запускаться в GameObject, содержащем Rigidbody, достигая вашего родительского сценария управления без необходимости писать дополнительный сценарий ретрансляции, который будет прикреплен к каждому коллайдеру.

Если вам нужно выяснить, кто из ваших дочерних коллайдеров участвовал в столкновении, вы можете сделать это следующим образом:

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

Одним из способов решения этой проблемы было бы иметь два сценария: один для объекта Enemy и другой для дочернего объекта (который необходимо назначить дочерним объектам Enemy).

Родительский скрипт

using UnityEngine;

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

Дочерний скрипт

using UnityEngine;

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

Таким образом, вы должны получать уведомления всякий раз, когда происходит столкновение с ребенком


2
Если вы используете подобное решение, и такие коллизии случаются часто, я настоятельно рекомендую, чтобы дети кэшировали GameObject получающего родителя. Это хорошая привычка в любое время, когда вы будете часто вызывать один и тот же GetComponent, и это позволит вам сделать любую хитрость - найти, какой родительский элемент в цепочке для отправки в «логику» нужно только один раз. Также помните, что transform.parent получит только непосредственного родителя.
Лунин

2

Вы можете просто передать верхний объект дочерним элементам и вызвать функцию непосредственно на нем. Это гарантирует, что вам не нужно полагаться на родительское распространение. Таким образом, вы не в конечном итоге делать глупые вещи, какtransform.parent.parent

Однако вы можете автоматизировать этот процесс с помощью GetComponentInParent . Это возвращает первый найденный скрипт. Затем кешируйте это в вашем объекте столкновения, непосредственно вызывайте функции для указанного кешируемого объекта.

В качестве альтернативы вы можете использовать UnityEvents (не используйте Messages) для привязки функций к дочернему объекту. С помощью событий единства вы можете добавить любого произвольного слушателя, чтобы вы могли сделать больше, чем просто уведомить объект верхнего уровня о попадании дочернего объекта.


1

Прямая цитата из ответов Unity (написанных Ашишем Двиведи ):

Добавьте скрипт в child и внутри него есть ссылка на скрипт родительского объекта. Теперь напишите 3 метода в родительском скрипте, таких как (OnCollisionEnter2DChild, OnCollisionStay2DChild, OnCollisionExit2DChild) и вызвали соответствующий метод из методов (OnCollisionEnter2D, OnCollisionStay2D, OnCollisionExit2D), передав в сценарий дочернего объекта, передав объект столкновения.


1

Вы можете выполнить проверку столкновения и посмотреть, в какой хит-бокс попали, а также получить точку удара, если это необходимо.

примечание: жесткое тело размещается на том же объекте, на котором установлен скрипт Collision Check.

Этот пример проверяет, какой хитбокс «снаряд» попал в цель.

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    
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.