繁体   English   中英

如何知道哪个碰撞器触发了对 Unity 中 OnTriggerEnter 的调用(在具有多个碰撞器的游戏对象上)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM