为什么碰撞反应允许反弹的球体最终通过平面

本文关键字:平面 碰撞 许反弹 为什么 | 更新日期: 2023-09-27 18:25:48

我目前正在Unity(C#)中复制一个粒子系统。我将物理添加到每个粒子(由球体表示)中,使其能够从位于原点的平面上反弹。受重力影响,粒子会反弹多次。当反弹变小时,球体开始穿过平面,直到最终落下。重力将持续作用在粒子上。将球体停在平面顶部的正确方法是什么?

到目前为止,我已经包含了我的实现,但代码最终总是允许球体穿过平面。

检测:

public bool SpherePlaneCollisionDetection(Particle part)
{
            Vector3 sphereCenter = part.position;
            Vector3 planeCenter = Vector3.zero;
            Vector3 normal = Vector3.up;
            double radius = 0.5;
            Vector3 dist1 = (sphereCenter - planeCenter);
            float finalDist = Vector3.Dot (dist1, normal);
            if (finalDist > radius) {
                    return false;
            } else {
            //Debug.Log ("COLLISION HAS OCCURED");
            //Debug.Log ("POSITION: " + part.position);
            //Debug.Log ("FINAL DIST: " + finalDist);
                    return true;
            }
    }

响应:

public void HandlePlaneCollision()
{
    for (int i=0; i<Particles.Count; i++) {
        //Particle p1temp = Particle[i];
        Particle tempParticle = (Particle)Particles[i];
        //Particle part = tempParticle.GetComponent<Particle>();

        float dampning = 0.8f;
        float bounce = -1f;
        if(SpherePlaneCollisionDetection(tempParticle))
        {
            tempParticle.velocity.y *= (bounce*dampning);
            tempParticle.velocity.x *= friction;
            tempParticle.velocity.z *= friction;
            Debug.Log(tempParticle.velocity.y);
            Particles[i] = tempParticle;
        }
    }
}

非常感谢您的帮助。

为什么碰撞反应允许反弹的球体最终通过平面

我不使用Unity,但我之前对物理模拟进行了编码,这种情况通常发生是因为:

  1. 阻尼+浮动圆误差

    是的,你是阻尼的,所以如果你的物体在下降,它会再次反弹(高度h0),再次下降,然后再次反弹(深度h1<h0)。。。所以它以越来越低的振幅振荡,但从不为零。

    如果你使用的引擎/框架进行了一些性能调整以加快碰撞测试,或者没有以比振荡更高的精度处理碰撞测试,那么它可能会错过边界命中,特别是在只有平面边界而不是体积的情况下,或者如果命中接近边界的顶点。

    您可以通过消除我在评论中提到的振幅较低的振荡来避免这种情况,因此:

    if (|speed|<some_minimal_safe_speed)然后将其设置为零以停止反弹,更好的是只保留表面切线速度部分而不是零

  2. 错误的边界定义

    一些边界碰撞测试系统要求以特定的方式定义边界对象,如

    • 多边形绕组
    • 按轴或某个角度排序
    • 按大小排序
    • 按命中概率排序

    因此,请在文档中检查它,并在需要时更正

  3. 采样率与模拟速度

    您正在采样对象的位置、速度、状态。。。在某些时间间隔内。在碰撞检测时间中,对象通常已经在边界表面以下/之后,但通常不完全(取决于速度和时间间隔)。当speed*time_interval足够高时,物体被检测为碰撞,因此其速度被表面反射并阻尼。

    但由于下一次迭代中的阻尼,位置仍然在边界后面,因此在迭代中,它被处理为正常的边界碰撞和反弹,以错误的方式进行。这种情况发生在较高的速度上,而不是较低的速度上。。。您可以通过将位置设置为表面命中点(如@Imapler所评论的)和/或+表面上的一些增量来防止这种情况