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