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
相关产品推荐
相关产品推荐

