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

Unity中同脚本GameObject碰撞时OnCollisionEnter执行两次的解决方法

解决办法:用唯一ID限制逻辑仅执行一次

Unity每个GameObject都有全局唯一的InstanceID,我们可以通过比较两个碰撞对象的ID,让只有ID更小(或更大)的对象执行碰撞逻辑,彻底避免两边重复触发。

修改后的代码如下:

private void OnCollisionEnter(Collision collision)
{
    if(collision.gameObject.tag == "Ship")
    {
        var shipBehaviour = collision.gameObject.GetComponent<ShipBehaviour>();
        if (shipBehaviour != null)
        {
            // 仅让InstanceID更小的对象执行逻辑,确保碰撞逻辑只跑一次
            if (GetInstanceID() < shipBehaviour.GetInstanceID())
            {
                if(shipBehaviour.ShipsInside > ShipsInside)
                {
                    shipBehaviour.ShipsInside -= ShipsInside;
                    Destroy(gameObject);
                }
                else if(shipBehaviour.ShipsInside < ShipsInside)
                {
                    ShipsInside -= shipBehaviour.ShipsInside;
                    Destroy(shipBehaviour.gameObject);
                }
                else
                {
                    Destroy(gameObject);
                    Destroy(shipBehaviour.gameObject);
                }
            }
        }
        return;
    }
}

原理说明

每个GameObject的InstanceID是Unity自动分配的唯一整数,碰撞的两个对象ID必然一高一低,因此只会有一个对象满足GetInstanceID() < shipBehaviour.GetInstanceID()的条件,逻辑只会执行一次,不会出现ShipsInside被重复修改的问题。

你也可以用布尔标记(比如在ShipBehaviour里加bool hasProcessedCollision)来控制执行,但InstanceID的方式更简洁,不需要额外维护状态变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:35:44