Search Unity

Why are simple sphere collisions with bounciness 1 not elastic?

Discussion in 'Physics' started by JohannesMP, Sep 1, 2019.

  1. JohannesMP

    JohannesMP

    Joined:
    Nov 4, 2016
    Posts:
    21
    The Setup

    Using Unity 2018.4 I've created a scene of identical spheres, each of which has a SphereCollider and a Rigidbody:



    Each sphere has a mass of 1, 0 friction, gravity disabled, and shares the same PhysicsMaterial with bounciness set to 1:



    Using a trivial script I can set the initial velocity of some of the spheres:

    Code (CSharp):
    1. public class InitialVelocity : MonoBehaviour
    2. {
    3.     public Vector3 startVelocity;
    4.  
    5.     void Start()
    6.     {
    7.         GetComponent<Rigidbody>().velocity = startVelocity;
    8.     }
    9. }
    10.  
    And set the initial velocities of the spheres as follows:



    The observed collisions all appear to be completely inelastic.

    The Question

    Why is this the case? Why are collisions between spheres with bounciness set to 1 not elastic? In fact in this case modifying the value of bounciness appears to have zero impact on the outcome.

    Unity's documentation describes PhysicsMaterial.Bounciness as a value of 1 meaning zero loss of energy - textbook definition of an elastic collision - and yet that is not what is observed. Assuming standard physics textbook rules of not losing energy to heat, there is a clear loss of energy in the first set of spheres colliding and canceling out each other's momentum completely. For energy to be conserved in this scenario they would need to reflect off each other at velocities equal in magnitude and opposite in direction.

    I am not asking for instructions on how to implement my own physics handling for elastic collisions between spheres. That is absolutely trivial here.

    I ask this question to understand why the observed behavior in this specific scenario appears to be in direct violation of the documentation and the common sense interpretation of what it means for two objects with 100% "bouniness" to collide.

    What is actually going on here? Am I misinterpreting how Unity defines bounciness?
     
    Last edited: Sep 1, 2019
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    There's a bounce threshold below which a collision is treated as inelastic. This can reduce jitter in more complex contact environments.

    In your simple test above, try lowering it: Physics.bounceThreshold
     
    JohannesMP likes this.
  3. JohannesMP

    JohannesMP

    Joined:
    Nov 4, 2016
    Posts:
    21
    That seems to work.


    With some further testing I noticed that a newly created PhysicsScene appears to internally use the default bounceThreshold value, and not the one that was set before it was created. If I set Physics.bounceThreshold again after the PhysicsScene's creation it does appear to now use the new value.

    So it appears PhysicsScene maintains its own internal bounceThreshold state, but after creation any changes to the static one will write to it as well.

    Since it has its internal state, is there a way to modify that separately?
     
    Last edited: Sep 12, 2019
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    I'm not a 3D physics dev (2D physics dev) but that doesn't sound correct. All those settings are global and are not associated with a PhysicsScene. The only one that I know of that is indirectly associated is gravity (that's associated with the physx/box2d world) which is why when gravity is set, it updates all active physics scenes (worlds).

    I'll have a look through the source for 3D physics and check that though. Give me a little time, it's Sunday and I've just got up!
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    Okay so looking at the 3D physics code, both gravity and bounce-threshold are stored within the Physx (3D) world. When you change that property, it iterates all active worlds and sets it.

    How physx handles this I don't know. It's likely that any existing contacts won't be affected by this but new ones presumably should be.

    Might be a bug in the scene creation code where it's not explicitly grabbing the current value when the scene is created.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    Yep, looks like that's a bug. It's grabbing a whole host of those global configuration options when you create a PhysicsScene but it's not grabbing the bounce-threshold. Could you report that as a bug and send me the report; I'll ensure it gets to the 3D physics devs quicker. I'll mention it regardless.
     
    Edy and JohannesMP like this.
  7. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,508
    As related question, bounceThreshold is now a global setting. Could it be turned into a per-rigidbody (or per-material) setting, or the way it works now is related to the PhysX design? Like specifying a "Physics.defaultBounceThreshold" value that could be changed later per-object. I could make very good use of that setting in a more granular way.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    I'm not the expert on physx here. All I know is that it's called on the physx world, it's not something Unity implements. If bodies or materials in physx have it then it could be exposed otherwise not.
     
    Edy likes this.
  9. JohannesMP

    JohannesMP

    Joined:
    Nov 4, 2016
    Posts:
    21
    Thanks for your help! I've submitted it as case 1181249
     
    MelvMay likes this.
  10. SeanParkinson

    SeanParkinson

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    17
    I have a fix for this, I will make sure it gets backported to 2018.4.
     
    JohannesMP and Edy like this.