Search code examples
c#unity-game-enginephysicscollisionparticle-system

Why is collision response allowing bouncing sphere to eventually pass through Plane?


I'm currently replicating a particle system in Unity (C#). I am adding physics to each particle (represented by a sphere) to allow it to bounce off a plane located at the origin. The particle bounces a number of times, being affected by gravity. As the bounces become smaller the sphere starts passing through the plane until finally falling through. The force of gravity will be continuously acting on the particle. What is the proper way to stop the sphere on top of the plane?

I have included my implementation thus far, but the code always eventually allows the sphere to fall through the plane.

DETECTION:

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;
            }
    }

RESPONSE:

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;
        }
    }
}

Any help is greatly appreciated.


Solution

  • I don't use Unity but I coded physics simulations before and this happens usually because:

    1. dampening + floating round errors

      yes you are dampening so if your object is falling then it bounces up again (height h0) falls again and then it bounces up again (height h1<h0) ... so it oscillates with lower and lower amplitude but never zero.

      if your used engine/framework has some performance tweaks to speed up the collision tests or does not handle collision test with higher precision then the oscillation then it can miss the boundary hit especial with just plane boundary instead of volumes or if the hit is close to vertex of boundary.

      You can avoid this by eliminating oscillations with lower amplitudes as mentioned in my comment so:

      if (|speed|<some_minimal_safe_speed) then set it to zero to stop bouncing even better would be left just surface tangent speed part instead of zero

    2. wrong boundary definition

      some boundary collision test systems require boundary objects to be defined in specific way like:

      • polygon winding
      • order by axis or some angle
      • order by size
      • order by probability of hit

      so check for it in documentation and correct if needed

    3. sampling rate vs. simulated speeds

      you are sampling object position,speed,state... in some time intervals. In collision detection time your object is usually already below/after the boundary surface but usually not completely (depends on speed and time interval). When the speed*time_interval is high enough then the object is detected as collided so its speed is mirror by the surface and damped.

      But due to dampening in next iteration the position is still behind the boundary so in the iteration after it is handled as normal boundary hit and bounce in the wrong way. This occurs on higher speeds not lower ones ... You can prevent this by setting the position to surface hit point (as @Imapler commented) and/or+some delta above surface