Єдність: як виявити зіткнення, що виникає на дочірньому об'єкті, з батьківського сценарію?


12

Я ворог, з цією структурою

  • Ворог
    • Тіло
      • Керівник
      • Рука ліва
      • Рука справа

І так далі.

У мене також є колайдер для кожної частини тіла. У своєму об'єкті "Ворог" я додав сценарій, і в цьому сценарії я хотів би перехопити можливе зіткнення (куля) для тіла, голови, руки, лівої тощо.

Чи є спосіб це зробити?

Відповіді:


16

Якщо ви використовуєте 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

Одним із способів вирішити це було б мати два сценарії: один для об'єкта Ворог та інший для дитини (який потрібно призначити дітям Ворога obj)

Батьківський сценарій

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 (не використовувати повідомлення) для прив’язки функцій до дочірнього об'єкта. За допомогою подій єдності ви можете додати будь-якого довільного слухача, щоб ви могли зробити більше, ніж просто повідомити об'єкт верхнього рівня про потрапляння дочірнього об’єкта.


1

Пряма цитата з відповідей "Єдність" (автор: Ашиш Двіведі ):

Додайте скрипт до дочірнього і всередині нього є посилання на скрипт батьківського об'єкта. Тепер напишіть у батьківському сценарії 3 методу, як (OnCollisionEnter2DChild, OnCollisionStay2DChild, OnCollisionExit2DChild) і викликайте відповідний метод із методів (OnCollisionEnter2D, OnCollisionStay2D, OnCollisionExit2D), які перебувають у дочірньому об'єктному скрипті, передаючи collision об'єкт, передаючи collision об'єкт.


1

Ви можете здійснити перевірку на зіткнення і побачити, в який ударний ящик потрапив, а також, якщо потрібно, отримати точку удару.

Примітка. Жорстке тіло розміщується на тому самому об'єкті, що має сценарій перевірки зіткнення.

Цей приклад - перевірка, щоб побачити, в яку скриньку потрапив «снаряд» у ціль.

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.