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.
I don't use Unity but I coded physics simulations before and this happens usually because:
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
wrong boundary definition
some boundary collision test systems require boundary objects to be defined in specific way like:
so check for it in documentation and correct if needed
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