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

如何检测带有Box Collider的汽车被撞击的侧面?

检测Box Collider被撞击的侧面(Unity)

核心思路是通过碰撞点的局部坐标判断撞击位置:将世界空间的碰撞点转换为汽车的局部空间,对比局部坐标中X/Z轴的绝对值,判断是左右侧还是前后侧碰撞,再根据坐标正负确定具体方向。

基础实现代码

将以下脚本挂载到带Box Collider和Rigidbody的汽车上:

private void OnCollisionEnter(Collision collision)
{
    // 获取首个碰撞接触点
    ContactPoint contact = collision.contacts[0];
    // 转换为汽车局部坐标
    Vector3 localHitPoint = transform.InverseTransformPoint(contact.point);
    
    // 假设Y轴向上,X轴对应左右,Z轴对应前后
    float absX = Mathf.Abs(localHitPoint.x);
    float absZ = Mathf.Abs(localHitPoint.z);
    
    Rigidbody rb = GetComponent<Rigidbody>();
    if (rb == null) return;

    if (absX > absZ)
    {
        // 左右侧碰撞
        if (localHitPoint.x > 0)
        {
            Debug.Log("右侧被撞击");
            rb.AddForce(transform.right * -500f, ForceMode.Impulse);
        }
        else
        {
            Debug.Log("左侧被撞击");
            rb.AddForce(transform.right * 500f, ForceMode.Impulse);
        }
    }
    else
    {
        // 前后侧碰撞
        if (localHitPoint.z > 0)
        {
            Debug.Log("后侧被撞击");
            rb.AddForce(transform.forward * -500f, ForceMode.Impulse);
        }
        else
        {
            Debug.Log("前侧被撞击");
            rb.AddForce(transform.forward * 500f, ForceMode.Impulse);
        }
    }
}

优化方案(更准确)

如果Box Collider未居中,或需要更稳定的判断,可以取所有碰撞点的平均位置,并修正Collider偏移:

private void OnCollisionEnter(Collision collision)
{
    BoxCollider boxCollider = GetComponent<BoxCollider>();
    Rigidbody rb = GetComponent<Rigidbody>();
    
    if (boxCollider == null || rb == null) return;
    
    // 计算所有碰撞点的平均局部位置
    Vector3 averageLocalHit = Vector3.zero;
    foreach (ContactPoint contact in collision.contacts)
    {
        averageLocalHit += transform.InverseTransformPoint(contact.point);
    }
    averageLocalHit /= collision.contacts.Length;
    
    // 修正Collider的中心偏移
    Vector3 adjustedHit = averageLocalHit - boxCollider.center;
    
    float absX = Mathf.Abs(adjustedHit.x);
    float absZ = Mathf.Abs(adjustedHit.z);
    // 根据碰撞相对速度动态调整力的大小
    float forceMultiplier = collision.relativeVelocity.magnitude * 100f;

    if (absX > absZ)
    {
        float direction = adjustedHit.x > 0 ? -1f : 1f;
        Debug.Log(adjustedHit.x > 0 ? "右侧被撞击" : "左侧被撞击");
        rb.AddForce(transform.right * direction * forceMultiplier, ForceMode.Impulse);
    }
    else
    {
        float direction = adjustedHit.z > 0 ? -1f : 1f;
        Debug.Log(adjustedHit.z > 0 ? "后侧被撞击" : "前侧被撞击");
        rb.AddForce(transform.forward * direction * forceMultiplier, ForceMode.Impulse);
    }
}

注意事项

  • 确保汽车对象挂载了Rigidbody组件,否则碰撞事件无法触发;
  • 若汽车的坐标系轴方向不同(比如Z轴是左右),只需调整代码中判断的轴即可;
  • 力的大小和模式可根据需求修改,ForceMode.Impulse适合模拟瞬时撞击力。

内容的提问来源于stack exchange,提问作者Mr. Gamer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:16:09