【问题标题】:How to know which collider triggered the call to OnTriggerEnter in Unity (on a gameobject with multiple colliders)如何知道哪个对撞机在 Unity 中触发了对 OnTriggerEnter 的调用(在具有多个对撞机的游戏对象上)
【发布时间】:2021-10-28 19:32:27
【问题描述】:

我最近遇到的一个问题如下。

我有一个带有 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 对象。

我已经找到了解决这个问题的方法,我将在此提供。也许它对遇到这个问题的任何人都有用。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    我的解决方案如下:

    首先我将以下脚本添加到我的项目中

    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) => Exit.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 中的触发事件,同时可以访问 enteredexitedincomingoutgoing 碰撞体。

    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 对象并在检查器中选择该函数。

    这让您可以在同一个文件中设置所有触发事件。

    注意:如果您不需要访问 enteredexited 碰撞器,但确实希望能够区分对不同触发器的调用,则可以使用我在这里展示的相同设置,但跳过结构。只需将UnityEvent&lt;OnTriggerDelegation&gt; 替换为UnityEvent&lt;Collider(2D)&gt; 并将other 传递给Enter.Invoke()。然后你的Player.cs 处理函数可能看起来像public void OnFeetTriggerEnter(Collision(2D) other)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多