Search Unity

Can I make 2d Physics bounce the same as the 'Multiply' bounce combine mode in 3d physics?

Discussion in 'Physics' started by Deleted User, Aug 5, 2017.

  1. Deleted User

    Deleted User

    Guest

    In 3D physics materials, we have the setting "Bounce Combine" which decides how the two phys materials in the collision combine to determine the overall bounce of the collision. The choices are Average (of the two bounciness values), Minimum, Maximum, and Multiply which just multiplies the bounciness values together

    Multiply is the mode I really want, but this setting of 'Bounce Combine' is not available for 2D Physics materials, and the way it works by default is the equivalent of 'Maximum'.

    In a previous engine I used, I could edit a single line in box2d directly, but as far as i know, this is off limits in unity, so I feel like i'd have to recreate my own bounce code using OnCollisionEnter2d collision contacts, and reduce all physics materials bounciness to 0

    Does anyone have any other ideas? Or how to go about making this code? Getting circles to bounce correctly off flat kinematic objects seems okay, but when it's boxes and other shapes, and they're bouncing against other moving things, I have no idea how to code for that. Another approach could be to set bounciness of all phys materials to 1 and instead reduce the velocity according to my own bounciness value, but i don't know if this is any easier.

    I'd appreciate any input, thanks!
     
  2. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    conuletv likes this.
  3. Deleted User

    Deleted User

    Guest

    I know about how to get contact information, (can also get the info from OnCollisionEnter/Stay2D) I just don't know what to do with the information to get a good bouncing behavior. Ultimately I think I need to add impulses at contact points in the normal direction, but how to calculate it correctly using the contact info is beyond me.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Unity uses default Box2D implementation:
    https://github.com/erincatto/Box2D/blob/master/Box2D/Dynamics/Contacts/b2Contact.h#L35

    Friction is combined as "Multiply", and bounce is combined as "Maximum". The justification is stated in the code comments:

    /// Friction mixing law. The idea is to allow either fixture to drive the friction to zero.
    /// For example, anything slides on ice.

    /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
    /// For example, a superball bounces on anything.
     
    Last edited: Nov 26, 2018
  5. Deleted User

    Deleted User

    Guest

    Yeah, Edy, I saw that line on the box2d github, I don't agree with their idea

    I'm making a physics-based platformer (character has a lot of momentum and mechanics use physics, it's deliberately not a conventional feeling platformer), and the character should be totally inelastic. Currently, because of the maximum combine mode, the character and the ground both need to be 0 bounciness, but the character can also jump and move on top of any physics object that is big enough, so i'd need to make all of those things 0 bounciness too.. this sucks cos then nothing is bouncy, it looks strange seeing boxes and other stuff not have any bounce when hitting the ground.

    Also it seems to me that the maximum bounce mode is wrong from a realistic standpoint, nothing in real life acts like their 'superball', the bounciest things are stuff like rubber balls, but a sponge could totally absorb their bounce

    It's also really frustrating that the line in box2d is so simple.. all i'd need to change is
    return restitution1 > restitution2 ? restitution1 : restitution2
    to
    return restitution1 * restitution2
     
    Last edited by a moderator: Aug 6, 2017
  6. Deleted User

    Deleted User

    Guest

    I've kinda solved my problem, I've imported Photon's 'TrueSync' asset, it includes Farseer which is a port of Box2d and I can edit the line mentioned in the previous comment. Haven't implemented t it yet though, seems like a lot of work, but I'm planning on doing networking anyway so this could be a good thing.
     
  7. Cookie042

    Cookie042

    Joined:
    Nov 25, 2013
    Posts:
    9
    "/// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
    /// For example, a superball bounces on anything.
    "
    this is so wrong it bothers me quite a lot. it has hindered several projects and forced me to use the 3D engine instead simply so i can change it to multiply.

    Here is my simple justification for why their statement is totally wrong
    This really needs to be fixed, this is how it should be.

    //different materials with different bounciness
    steel ball bounciness = .95f
    marble slab bounciness = .95f
    wood slab bounciness = .5f
    mud bounciness = 0.0f

    //example cases
    steel + marble slab = 0.90f
    steel + wood slab = 0.475f
    steel ball + mud = SHOULD equal 0.0f.

    In unity with the above you simply get .95f in all cases and it makes NO sense. What the ball is hitting matters! a steel ball does not bounce on mud. nor does a "superball"

    sure, you could set the steel ball to zero bounce and that would half work, until you had 2 steel balls colliding with each other as well as hitting different materials around the scene.

    you could solve this by changing bounciness values before the collision happens with a trigger volume...but what a pain that is. and it also adds other incorrect corner cases.

    Now, for some actual physics justification
    "The COR (Coefficient of restitution) is a property of a pair of objects in a collision, not a single object. If a given object collides with two different objects, each collision would have its own COR. When an object is described as having a coefficient of restitution, as if it were an intrinsic property without reference to a second object, it is assumed to be between identical spheres or against a perfectly rigid wall."
    https://en.wikipedia.org/wiki/Coefficient_of_restitution#Paired_objects

    in the case of unity, the bold statement is rendered invalid. cause it doesn't matter what the second objects COR is. it will always just use the maximum

    it should atleast give the option to change it.
     
    HelpMePlease32 likes this.
  8. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Mud is not an inelastic surface. Box2D assumes inelastic surfaces, so no surface is allowed to reduce the bounciness of other objects.
     
  9. AndreaGiulianoK

    AndreaGiulianoK

    Joined:
    Mar 11, 2015
    Posts:
    6
    Just change the speed of the rigidbody after the collision in accordance with the bounciness value of the other material.

    Here is a simple solution for single collisions (not multiple or angles).
    To be assigned to the bouncing object (with rigidbody).
    Code not optimized.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class AverageBounce : MonoBehaviour
    4. {
    5.     private void OnCollisionEnter2D(Collision2D other) {
    6.         // Obtain bounciness from the two Colliders ( or Rigidbodies)
    7.         float myB = GetComponent<Collider2D>().bounciness;
    8.         float otherB = other.collider.sharedMaterial.bounciness;
    9.         // Average Bounciness
    10.         float averageBounciness = (otherB+myB)/2;
    11.         // Select the Max bounciness
    12.         float max = myB > otherB ? myB : otherB;
    13.         // Modify object velocity according to the new bounciness
    14.         GetComponent<Rigidbody2D>().velocity *= averageBounciness/max;
    15.     }
    16. }
     
    Last edited: May 7, 2020