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

Unity中OnCollisionEnter设置Rigidbody.useGravity失效且碰撞偶发失败

问题根因分析
  • 核心错误:直接调用transform.Translate()移动挂载了Rigidbody的物体,该方法会直接修改物体世界坐标,完全绕过Unity物理引擎的碰撞计算流程,你设置的Continuous连续碰撞检测仅对通过Rigidbody API(AddForce、直接赋值velocity等)驱动的物体生效,对手动瞬移的物体无效,偶发碰撞成功只是因为两帧之间的位移量刚好没完全穿过碰撞体,属于巧合。
  • 逻辑冲突:你自己手写了一套重力计算逻辑,和Rigidbody原生重力逻辑冲突,且移动逻辑放在LateUpdate执行,相当于每次物理引擎计算完碰撞后,你又把物体瞬移走了,碰撞检测自然无法稳定触发。
  • 状态切换逻辑死循环:你仅在OnCollisionEnter里才关闭手动移动逻辑,本身就要求碰撞检测先触发才能停止瞬移,完全卡死了正常碰撞的触发条件。
修复方案

完全丢弃transform.Translate移动逻辑,所有位移交给物理引擎处理,仅在初始化时给炸弹赋值初速度,后续重力、碰撞检测都用Unity原生物理逻辑实现即可,修改后代码如下:

using UnityEngine;
public class BombBehavior : MonoBehaviour
{
    [SerializeField] float ExplosionForce = 300;
    [SerializeField] float ExplosionRadius;
    [SerializeField] float LaunchForceX;
    [SerializeField] float LaunchForceY;
    [SerializeField] float Delay;
    float countdown;
    Rigidbody rigidbodyy;
    Player player;
    bool HasExploded = false;

    void Start()
    {
        rigidbodyy = GetComponent<Rigidbody>();
        player = Player.p;
        // 直接通过刚体API设置初速度,所有位移交给物理引擎处理
        float finalX = transform.position.x > player.transform.position.x ? LaunchForceX : -LaunchForceX;
        rigidbodyy.velocity = new Vector3(finalX, LaunchForceY, 0);
        // 直接开启原生重力,不用手写模拟
        rigidbodyy.useGravity = true;
        countdown = Delay;
    }

    private void Update()
    {
        countdown -= Time.deltaTime;
        if (countdown <= 0 && !HasExploded)
        {
            ExplodeNearEnemy();
        }
    }

    private void ExplodeNearEnemy()
    {
        HasExploded = true;
        Collider[] colliders = Physics.OverlapSphere(transform.position, ExplosionRadius);
        foreach (Collider collider in colliders)
        {
            if (collider.gameObject.CompareTag("Enemy"))
            {
                Rigidbody enemyRB = collider.GetComponent<Rigidbody>();
                if (enemyRB != null)
                {
                    enemyRB.useGravity = true;
                    enemyRB.AddExplosionForce(ExplosionForce, transform.position, ExplosionRadius);
                    Destroy(enemyRB.gameObject,1);
                }
            }
        }
        Destroy(gameObject);
    }

    private void OnCollisionEnter(Collision collision)
    {
        // 此处可扩展碰撞后的自定义逻辑,比如碰地面直接爆炸
    }
}
补充优化设置
  • 炸弹优先用SphereCollider、CapsuleCollider等简单碰撞体,比ProBuilder生成的网格碰撞体检测效率高、漏检率低,如果必须用网格碰撞体请勾选Convex选项
  • 如果炸弹飞行速度很快,可以把碰撞检测模式改成Continuous Dynamic,对高速移动的小物体碰撞检测更精准
  • 地板的碰撞体不要用MeshCollider,优先用BoxCollider等简单碰撞体,ProBuilder生成的复杂MeshCollider会大幅提升漏检概率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 15:06:08