You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何OnTriggerEnter2D会被非触发器碰撞体触发且重复执行两次

问题根因

  • 你使用的玩家对象挂载了2个Collider2D,根据Unity 2D的碰撞触发规则:只要碰撞双方任意一方的碰撞体勾选了isTrigger,且满足层级碰撞设置,就会向双方挂载的所有MonoBehaviour发送OnTriggerEnter2D消息。玩家的两个碰撞体(无论自身是否为触发器)和掉落物的触发器碰撞体接触时,会各自触发一次事件,因此逻辑执行了两次。
  • Destroy方法不会立即销毁对象,会等待当前帧的所有逻辑执行完成后才销毁对象,因此第一次执行销毁后,第二次触发的判断逻辑仍然可以访问到未被销毁的掉落物对象,判断条件依然成立。

可行解决方案

方案1:给掉落物添加拾取状态标记(最便捷)

在DroppedItem脚本中新增拾取状态字段,处理拾取逻辑前先校验状态,避免重复处理:

// 先修改DroppedItem类,新增字段
public class DroppedItem : MonoBehaviour
{
    public Item item;
    public int itemAmount;
    // 新增拾取状态标记,默认未拾取
    private bool _isPicked = false;
    public bool IsPicked => _isPicked;

    public void MarkPicked()
    {
        _isPicked = true;
    }
}

// 再修改你的触发逻辑
private void OnTriggerEnter2D(Collider2D other)
{
    DroppedItem item = other.GetComponent<DroppedItem>();
    if (item != null && other.isTrigger && !item.IsPicked)
    {
        item.MarkPicked();
        Debug.Log("Picked up item.");
        inventory.AddItem(item.item, item.itemAmount);
        Destroy(item.gameObject);
    }
}

方案2:通过层级过滤避免重复触发

将玩家的两个碰撞体分配到不同层级:

  • 处理常规碰撞的非触发器碰撞体分配到Player层
  • 处理受击、拾取的触发器碰撞体分配到独立的PlayerInteraction层
    在Unity的项目设置-物理2D-碰撞矩阵中,设置掉落物所在的层级仅能和PlayerInteraction层触发碰撞,即可避免玩家的常规碰撞体和掉落物触发事件。

方案3:分离碰撞体的挂载对象

将玩家的受击/拾取触发器单独挂载到玩家的子对象上,把拾取逻辑也移到该子对象的脚本中,只有该子对象的触发器产生碰撞时才会执行拾取逻辑,不会受到主对象常规碰撞体的影响。

内容的提问来源于stack exchange,提问作者TahaSener07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:45:06