Как узнать, какой коллайдер вызвал вызов OnTriggerEnter в Unity (на игровом объекте с несколькими коллайдерами)

#c# #unity3d

Вопрос:

Проблема, с которой я недавно столкнулся, заключалась в следующем.

У меня был объект игрока с Player прикрепленным к нему сценарием.

Моя иерархия игровых объектов выглядела примерно так:

введите описание изображения здесь

 Player (parent) // Has Player.cs and a RigidBody attached to it.  - GFX // Holds graphics like sprites  - PhysicsHolder // Empty object  - Body // Has a box trigger 2d defining the player body  - Feet // Has a box trigger 2d defining the player feet area  

Я хотел обработать все события столкновения для моего игрока в Player.cs, чтобы все они были в одном месте. Проблема заключалась в том, что было довольно трудно различить, к какому Feet объекту или Body объекту был обращен вызов OnTriggerEnter2D .

Если вы настроили свою иерархию, как я, триггеры «Тело» и «Ноги» вызовут OnTriggerEnter2D в своем родительском сценарии и, таким образом, вызовут Player.OnTriggerEnter2D .

В OnCollisionEnter нем вы получаете ссылку на коллайдер, с помощью которого был инициирован вызов collision.other . Затем вы можете легко установить тег для каждого соответствующего коллайдера и сделать collision.other.CompareTag()

Поскольку OnTriggerEnter у вас нет Collision объекта в качестве парама , но a Collider2D , и у a Collider2D нет ссылки other или чего-то подобного, вы не можете сделать то же самое в случае, когда вы хотите обработать событие триггера. Использование this.CompareTag() in Player.cs также не будет достаточным, так как вы будете сравнивать тег родительского объекта игрока, а не объект «Ноги» или «Тело».

С тех пор я нашел решение этой проблемы, которое приведу здесь. Может быть, это пригодится любому из вас, кто столкнется с этой проблемой.

Ответ №1:

Мое решение было следующим:

Сначала я добавил в свой проект следующий скрипт

 using UnityEngine; using UnityEngine.Events;  /// lt;summarygt; /// Delegates the call to OnTrigger2D for this object to another object. /// lt;/summarygt; public class OnTrigger2DDelegator : MonoBehaviour {  private Collider2D caller;   private void Awake()  {  caller = GetComponentlt;Collider2Dgt;();  }   [Tooltip("Which function should be called when trigger was entered.")]  public UnityEventlt;OnTriggerDelegationgt; Enter;   [Tooltip("Which function should be called when trigger was exited.")]  public UnityEventlt;OnTriggerDelegationgt; Exit;   void OnTriggerEnter2D(Collider2D other) =gt; Enter.Invoke(new OnTriggerDelegation(caller, other));  void OnTriggerExit2D(Collider2D other) =gt; Exit.Invoke(new OnTriggerDelegation(caller, other)); }  /// lt;summarygt; /// Stores which collider triggered this call and which collider belongs to the other object. /// lt;/summarygt; public struct OnTriggerDelegation {   /// lt;summarygt;  /// Creates an OnTriggerDelegation struct.  /// Stores which collider triggered this call and which collider belongs to the other object.  /// lt;/summarygt;  /// lt;param name="caller"gt;The trigger collider which triggered the call.lt;/paramgt;  /// lt;param name="other"gt;The collider which belongs to the other object.lt;/paramgt;  public OnTriggerDelegation(Collider2D caller, Collider2D other)  {  Caller = caller;  Other = other;  }   /// lt;summarygt;  /// The trigger collider which triggered the call.  /// lt;/summarygt;  public Collider2D Caller { get; private set; }   /// lt;summarygt;  /// The other collider.  /// lt;/summarygt;  public Collider2D Other { get; private set; } }  

Большая часть объяснений уже содержится в резюме, которое я написал, но вот еще несколько деталей.

Добавление этого скрипта, например, к Feet объекту (который, помните, имеет BoxCollider2D, который является триггером, представляющим ноги моего игрока), добавит некоторые поля в инспектор. Затем вы можете перетащить свой объект плеера и выбрать, какая функция должна выполняться на объекте плеера.

Если мы теперь добавим следующий код к нашему Player.cs , мы сможем обработать событие триггера Player.cs , имея доступ как к введенному или выведенному, так и к входящему или исходящему коллайдерам соответственно.

 public void OnFeetTriggerEnter(OnTriggerDelegation delegation) {  // will print out "Feet" in my example  Debug.Log(delegation.Caller.name);   // will print out "Ground" in my example if the feet trigger was entered by an object called Ground.  Debug.Log(delegation.Other.name);  }  

Выбор этого метода в разделе OnTrigger2DDelegator в инспекторе затем дает что-то похожее на это:

добавлены поля в инспекторе

И вуаля! Теперь вы можете добавить еще одну функцию в Player.cs , например OnBodyTriggerEnter , добавить другого делегатора в объект тела и выбрать функцию в инспекторе.

Это позволяет вам настроить все ваши триггерные события в одном файле.

Примечание: Если вам не нужно обращаться к введенному или выведенному коллайдеру, но вы хотите различать вызовы разных триггеров, вы можете использовать ту же настройку, которую я показал здесь, но пропустите структуру. Просто замените UnityEventlt;OnTriggerDelegationgt; на UnityEventlt;Collider(2D)gt; и перейдите other на Enter.Invoke() . Тогда ваши Player.cs функции обработки могут выглядеть примерно так public void OnFeetTriggerEnter(Collision(2D) other)