[英]How to know which collider triggered the call to OnTriggerEnter in Unity (on a gameobject with multiple colliders)
我最近遇到的一个问题如下。
我有一个 Player 对象,上面有一个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
的调用。
如果您像我一样设置了层次结构,则 Body 和 Feet 触发器都将在其父脚本中调用 OnTriggerEnter2D ,因此将调用Player.OnTriggerEnter2D
。
在OnCollisionEnter
您可以获得对碰撞器的引用,该碰撞器触发了带有collision.other
的调用。 然后您可以轻松地为每个各自的碰撞器设置一个标签并执行collision.other.CompareTag()
由于OnTriggerEnter
没有Collision
对象作为参数,而是Collider2D
,并且Collider2D
没有对other
或类似内容的引用,因此在您想要处理触发事件的情况下,您不能这样做。 在Player.cs
使用this.CompareTag()
也不够,因为您要比较父 Player 对象的标签,而不是 Feet 或 Body 对象。
我已经找到了解决这个问题的方法,我将在这里提供。 也许它对遇到此问题的任何人都有用。
我的解决方案如下:
首先,我将以下脚本添加到我的项目中
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// Delegates the call to OnTrigger2D for this object to another object.
/// </summary>
public class OnTrigger2DDelegator : MonoBehaviour
{
private Collider2D caller;
private void Awake()
{
caller = GetComponent<Collider2D>();
}
[Tooltip("Which function should be called when trigger was entered.")]
public UnityEvent<OnTriggerDelegation> Enter;
[Tooltip("Which function should be called when trigger was exited.")]
public UnityEvent<OnTriggerDelegation> Exit;
void OnTriggerEnter2D(Collider2D other) => Enter.Invoke(new OnTriggerDelegation(caller, other));
void OnTriggerExit2D(Collider2D other) => Enter.Invoke(new OnTriggerDelegation(caller, other));
}
/// <summary>
/// Stores which collider triggered this call and which collider belongs to the other object.
/// </summary>
public struct OnTriggerDelegation {
/// <summary>
/// Creates an OnTriggerDelegation struct.
/// Stores which collider triggered this call and which collider belongs to the other object.
/// </summary>
/// <param name="caller">The trigger collider which triggered the call.</param>
/// <param name="other">The collider which belongs to the other object.</param>
public OnTriggerDelegation(Collider2D caller, Collider2D other)
{
Caller = caller;
Other = other;
}
/// <summary>
/// The trigger collider which triggered the call.
/// </summary>
public Collider2D Caller { get; private set; }
/// <summary>
/// The other collider.
/// </summary>
public Collider2D Other { get; private set; }
}
大多数解释已经在我写的摘要中,但这里有一些更详细的信息。
将此脚本添加到例如Feet
对象(记住,它具有 BoxCollider2D,这是代表我的玩家脚的触发器),将向检查器添加一些字段。 然后您可以拖入您的 Player 对象,并选择应该在 Player 对象上运行的函数。
如果我们现在将以下代码添加到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
,将另一个委托者添加到 body 对象并在检查器中选择该函数。
这使您可以在同一文件中设置所有触发事件。
注意:如果您不需要访问进入或退出的碰撞器,但确实希望能够区分对不同触发器的调用,您可以使用我在此处显示的相同设置,但跳过结构。 只需将UnityEvent<OnTriggerDelegation>
替换为UnityEvent<Collider(2D)>
并将other
传递给Enter.Invoke()
。 然后你的Player.cs
处理函数看起来像public void OnFeetTriggerEnter(Collision(2D) other)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.