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

如何计算冲击速度?解决OnCollisionEnter滚动触发音效问题

解决Unity中球掉落平面才播放碰撞音效的方案

核心思路是区分垂直冲击和水平滚动的碰撞场景,通过判断碰撞时的速度方向与碰撞面法线的关系,过滤掉滚动时的无效触发。

方案1:基于碰撞法线与速度的点积判断垂直冲击分量

这是最直接的方法,利用向量点积计算速度在碰撞面法线方向的分量,只保留垂直方向的冲击速度:

  • 先在OnCollisionEnter中获取碰撞接触点的法线(通常地面/平面的法线是向上的Vector3.up)
  • 计算球的速度与法线的点积:点积的正负代表速度方向与法线方向的关系,绝对值就是垂直方向的速度分量
  • 只有当垂直分量的绝对值超过设定阈值时,才播放音效,同时可通过标签过滤只处理地面碰撞

代码示例:

public AudioClip impactSound;
public float impactThreshold = 2f; // 可根据需求调整阈值
private Rigidbody rb;

void Start()
{
    rb = GetComponent<Rigidbody>();
}

void OnCollisionEnter(Collision collision)
{
    // 只处理标签为"Ground"的平面
    if (!collision.gameObject.CompareTag("Ground")) return;

    // 获取碰撞接触点的法线(取第一个接触点即可)
    Vector3 contactNormal = collision.contacts[0].normal;
    // 计算速度在法线方向的分量
    float verticalSpeedComponent = Vector3.Dot(rb.velocity, contactNormal);

    // 掉落时速度向下,与向上的法线点积为负,取绝对值判断是否达到冲击阈值
    if (Mathf.Abs(verticalSpeedComponent) > impactThreshold)
    {
        AudioSource.PlayClipAtPoint(impactSound, transform.position);
    }
}

方案2:结合碰撞前位置判断掉落状态

如果担心法线异常(比如倾斜地面),可以额外记录碰撞前一帧的物体位置,判断是否是从上方掉落:

  • 在FixedUpdate中记录球的上一帧位置
  • 碰撞时比较当前球的位置与碰撞点的位置,结合垂直速度分量双重判断

代码示例:

private Vector3 lastPosition;
private Rigidbody rb;
public AudioClip impactSound;
public float impactThreshold = 2f;

void Start()
{
    rb = GetComponent<Rigidbody>();
    lastPosition = transform.position;
}

void FixedUpdate()
{
    lastPosition = transform.position;
}

void OnCollisionEnter(Collision collision)
{
    if (!collision.gameObject.CompareTag("Ground")) return;

    Vector3 contactPoint = collision.contacts[0].point;
    // 判断上一帧位置是否高于碰撞点(说明是从上方掉落)
    bool isFallingFromAbove = lastPosition.y > contactPoint.y + 0.1f; // 0.1f是容错值,避免精度问题
    float verticalSpeed = Mathf.Abs(rb.velocity.y);

    if (isFallingFromAbove && verticalSpeed > impactThreshold)
    {
        AudioSource.PlayClipAtPoint(impactSound, transform.position);
    }
}

方案3:用射线预判碰撞(适合复杂场景)

如果场景中有高低起伏的地面,可通过射线预判即将发生的碰撞,提前获取垂直速度:

  • 每一帧向球的下方发射射线,检测地面
  • 当射线检测到地面且距离小于阈值时,记录此时的垂直速度
  • 碰撞发生时用记录的预判速度判断是否播放音效

这个方案能更精准地过滤滚动时的误触发,但需要额外的射线检测开销,适合对精度要求高的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:45:41