How to get a perfect bouncing ball

In the unity physics system, It may be hard to get a perfect bouncing ball.

Bounciness is 1 and drags,frictions are all 0.

In my thought , it will be a perfect bouncing ball, but it isn’t.

It is getting more and more energy.

So, I want to know how to get a perfect bouncing ball in 3D.

In case,

Let me explain my program .

In the cube, there are 300 spheres. they collide with each other and cube.!

I know this sounds sad, but I spent about five mins trying to figure out how close you can get to perfect bounces with the physic material.

  1. Create a physic material
  2. Set the bounce combine to maximum
  3. Change bouciness to 0.9699999 exact

I don’t know if its much different to that but I put a background behind it and I saw it reach the same point.

I’d be happy to be proved wrong but as far as I know Unity and/or nVidia don’t publish the equations uses for PhysX calculations, nor make anything like physic materials user extendable, so it is basically impossible to construct accurate physics systems based on precisely researched values. Unfortunately this seems to extend to edge cases like elastic collisions (zero energy loss). I’ve seen the same thing where full bounciness with zero friction and drag results in energy being added, and balls gaining rotational energy when they should be slowing down due to friction. I’m not sure if this is a floating point math issue, a bug, or a known limitation.

Fortunately elastic collisions with fixed surfaces are easy enough to calculate yourself. Forget Physic Materials and do something like this:

  • Don’t use Unity collision handling (not sure if this is possible when using OnCollisionEnter)
  • Use OnCollisionEnter or OnTriggerEnter to be alerted when a collision occurs
  • OnCollisionEnter: Calculate the average of the normals of the collision… OnTriggerEnter: use a Raycast to find the collision surface and get the normal
  • Use Vector3.Reflect to reflect velocity: “rigidbody.velocity = Vector3.Reflect(rigidbody.velocity, normal);”

For my game Stryker: First Person Football I had to use a hybrid custom + PhysX physics system to work around the limitations of the builtin Unity Physics, including modifying the dynamic friction based on the speed of the ball. It’s far from perfect but the result is fairly realistic.

SOLVED

I had the same issue and resolved it without any code. My bouncing object was gaining kinetic energy with each bounce.

The issue was that the collision detection property was set to discrete.

Go into the rigidbody component and set the collision detection to continuous. That’s it.

void OnCollisionEnter ( Collision collision )
{		
  rigidbody.velocity = new Vector3( collision.relativeVelocity.x , collision.relativeVelocity.y , 0 );
}

I found that it only bounces perfectly (reaches the exact same height each time it bounces) if the “Linear Drag” and “Angular Drag” properties are set to 0 and the “Collision Detection” property is set to “Discrete” on the Rigidbody (I am using a 2D Rigidbody).
The Physics material must have exactly 1Bounciness” and 0Friction”.

in our ball player script use this line of code assists>>>

void OnCollisionEnter ( Collision collision )
{
  _rigidbody.velocity = new Vector3 (collision.relativeVelocity.x, collision.relativeVelocity.y);
}

Perfect Bounce:

using UnityEngine;

public class Bounce : MonoBehaviour
{
    Rigidbody2D rb;
    public float force = 10;
    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        rb.AddForce(Vector2.up * force, ForceMode2D.Impulse);
    }
}

No, this is a perfect bounce, unless you want an impulse each bounce using acceleration makes the bounces higher, consistently over time.

void OnCollisionEnter ( Collision collision )
{
    // Get the contact point's normal (opposite direction)
    Vector3 collisionNormal = collision.contacts[0].normal;

    // Apply force in the opposite direction of the collision normal
    rb.AddForce(-collisionNormal * bounce, ForceMode.Acceleration);
}

alternatively

rb.AddForce(Vector2.up * bounce, ForceMode.Acceleration);

Works as well. Use both in tandum for a even more realistic bounce :wink:

Note: you need to use larger numbers for Acceleration something like 100-1000