Search Unity

2d ball (sprite) bouncing is unnatural - keeps bouncing (when in reality it will be rolling)

Discussion in '2D' started by mosh999, May 12, 2019.

  1. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Hi all,

    I am facing a problem with my 2d physics game.

    I have a simple 2d simulation where I have ball sprite, with 2d rigidbody and a platform.
    The rigid body has a gravity scale applied and has a material with bounciness applied.

    When the game starts, the ball drops and bounces as it should and eventually gets close to the platform. When the ball is virtually touching the floor and not even moving, it seems that it's actually still colliding against the platform several times per second - I can tell this because I have created a variable which counts the number of collisions of the ball against the platform (incremented by each call to OnCollisionEnter2D on the ball's controller script).

    To give an example of various settings i've tested with:

    Ball gravity scale can be set to 2, or 9.8.
    Ball bounciness=0.5, 0.7
    Mass of ball = 1, or 10, or 20

    In each of these cases, ball keeps bouncing hundreds of times even when it's virtually touching the floor and you can visually see a mini bounce occur.

    This behaviour does not reflect the real world physics. I don't know how to fix this problem. Perhaps there is a reasonable explanation for this and there are configuration settings that can fix the issue.

    It seems is a very elementary problem I'm facing, so I am hopeful that there is a simple solution out there for this. I have read the forums and found no appropriate answer.

    I would really appreciate if someone can get back to me asap as it's blocking all my progress at present.

    Many Thanks
     
  2. justLC

    justLC

    Joined:
    Oct 16, 2018
    Posts:
    45
    Could you make a screenshot or something because it's hard to imagine the exact scenario :)
    So what I first thought is, maybe your bounciness is too high for that low of a mass. But if you need such a high bounciness and such a low mass at the same time, my approach would be something like making a simple script that enhances mass or reduces bounciness for a very small time frame after you detected too many collisions in a short interval.
     
  3. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Hello,

    First and foremost, I would like to thank you so much for responding to this. My first post on this topic was made months ago and nobody within the unity support / community actually responded. I'm relatively new to unity, so I was beginning to believe these forums were pointless and I stopped working on my project entirely as I didn't have any money to invest on this project.

    Let me try to provide more details on the problem.

    GAME SETUP

    The game starts off on this screen with a ball shown at rest position:

    start_position.png

    The objects of importance on this screen is the ball & the background (which has 4 collider 2d objects to represent the walls, the ceiling and the floor).

    The ball has the following properties:
    ball properties.png

    The Ball Material referenced above is here:
    ball_material.png

    RUNNING THE GAME

    The ball drops due to gravity and starts losing energy after each bounce like a real ball should.

    Here is a screen shot of the ball after about a few bounces and once it is virtually touching the floor:
    infinite_bounce_1.png

    Circled in red, you'll see the number 56 which means there have been 56 bounces since the ball was dropped & the (x,y) velocity.

    This bounce number increments on each collision with the floor and is defined in a simple one line of code within OnCollisionEnter2D of the ball's controller script, the velocity is displayed using rb2d.velocity.

    From this point onwards, the ball continues infinitely bounce up and down moving a distance of about a millimetre vertically each time.

    Here is another screenshot 30 seconds later:
    infinite_bounce_2.png

    You can see the number of bounces are now 248. This means it's done about 192 bounces in 30 seconds.

    SUMMARY?

    This is the infinite ball bouncing problem that i'm facing. This should provide sufficient info to determine the problem and figure out an appropriate solution.

    I've tried making the following changes to address the problem but it did not help:
    - increasing the mass to 5, or 10, or even 30.
    - decreasing the bounciness of the ball material to a very low value e.g. 0.1.

    The above actions only changed the game behaviour insofar as making the ball reach close to the floor more quickly, but once it reaches the floor it infinitely bounces like before.

    I welcome responses from anyone who can provide thoughts or solutions to this.

    Thank you in advance for any time you invest as I will be infinitely grateful once i've got this resolved as it will allow me to build my game which i've been sitting on for years.

    Many Thanks in advance!
     
    Last edited: May 12, 2019
  4. justLC

    justLC

    Joined:
    Oct 16, 2018
    Posts:
    45
    Attach the BallMaterial to the Rigidbody2D and not to the CircleCollider2D.
     
  5. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Thanks for the suggestion.
    I just tried out your suggestion, but it never made a difference unfortunately.
     
  6. Green11001

    Green11001

    Joined:
    Apr 14, 2018
    Posts:
    397
    could you just set the velocity to 0 if its below a certain amount and above another amount?
     
  7. justLC

    justLC

    Joined:
    Oct 16, 2018
    Posts:
    45
    Hmm maybe my suggestion didn't work because Collision Detection is not set to Continuous. Could be worth a try ^^

    Edit: One more idea. I see you have a "FloorBouncy" material. Maybe the problem is caused by having bounciness on both colliding objects.
     
  8. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Setting Collision detection to 'Continuous' actually made a difference.

    To be specific, this change has allowed the ball to now fully 'stop' bouncing some of the time, but not all :)

    It still goes into that infinite loop some of the time. We're heading in the right direction though. Feels great to see the ball behave itself and stay put. :).

    In case you're wondering in what manner the ball is bouncing, i am using a method in the Player Controller script which allows one to use the keyboard arrow keys to exert horizontal or vertical forces on the ball. This allows me to test moving the ball around & making it bounce from different angles etc. Here is the code for the method:

    Code (CSharp):
    1.     void FixedUpdate()
    2.     {
    3.         float moveHorizontal = Input.GetAxis("Horizontal");
    4.         float moveVertical = Input.GetAxis("Vertical");
    5.         Vector2 movement = new Vector2(moveHorizontal, moveVertical);
    6.         rb2d.AddForce(movement * speed);
    7.         //updateInfo();
    8.     }
    On a side note, to answer your question on the topic of FloorMaterial bounciness, this property seems to have no impact as i've already tested enabling and disabling the floor material and it resulted in no visible difference in the outcome.
     
  9. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Thanks - I've explored this option before. I don't want to create 'hacks' which alter the way the natural physics should be working. The Unity API should be able to simulate the real world physics of balls bouncing ... Correct physics behaviour is essential to my Game.
     
  10. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Any additional thoughts on this dilemma from the community?

    It's still not resolved as it bounces forever most of the time, apart from an odd few.

    I'm beginning to think it could be a bug with the unity 2D Physics library. Why have I reached this conclusion? well, i've come across some code in 3d where the balls seem to be coming to rest and do not continue bouncing indefinitely.

    In addition, is there anyone from unity who can comment on this too?

    (note i still encourage anyone to comment on this, as I need all the help I can get ... )
     
    Last edited: May 16, 2019
  11. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    You should not apply a force to the ball if there's no input. Always adding a force stops the ball from ever going to sleep. Check its sleep state by going into the Inspector for the ball Rigidbody2D in the Info roll-out.
     
    dan_ginovker likes this.
  12. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Thanks for your thoughts.

    I've checked that the sleep mode is set to 'Start Awake' for the ball.

    Can you elaborate on your statement about 'You should not apply a force to the ball if there's no input'?

    If there is no input, would it not be the case that movement is zero and therefore a force of 'zero' is applied? (i'll do some testing around this of course ..)
     
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    That's not what I suggested. I said, "going into the Inspector for the ball Rigidbody2D in the Info roll-out". This shows the sleep state, not what the initial sleep mode is. You can see the "Info" rollout in the inspector here.



    Adding a force of zero is not only wasteful it causes the underlying physics system (Box2D) to wake the body. Making assumptions like that, expecting things to be caught for you can mean you run into issues like this. As a rule, don't ask the physics system to do nothing. :)
     
    Last edited: May 18, 2019
  14. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Hi There,
    Followed your advice to do the following:
    1. I checked the 'sleep state' using the info rollout to check that it is in a state of 'Awake' in the instance where it is bouncing forever.
    2. I've also changed the FixedUpdate() method so that it's not adding redundant forces:

    Code (CSharp):
    1.  void FixedUpdate()
    2.     {
    3.         float moveHorizontal = Input.GetAxisRaw("Horizontal");
    4.         float moveVertical = Input.GetAxisRaw("Vertical");
    5.          
    6.         if(moveHorizontal != 0 || moveVertical != 0)
    7.         {
    8.             Vector2 movement = new Vector2(moveHorizontal, moveVertical);
    9.             rb2d.AddForce(movement * speed);
    10.         }
    11.  
    12.     }
    13.  
    Things have improved slightly in some ways. I am seeing the following outcome:
    - The vertical speed seems to be reaching 'zero' more often than before. However, this seems to be only in cases where the bounciness of the ball material is around 0.6. For bounciness values values > 0.7, the vertical speed may never reach zero.
    - With a bounciness of 0.6, whilst the vertical speed is reaching zero it seems like the horizontal speed seems to remain forever (at a tiny value).

    Overall, whilst things are better it looks like there is some other factor which is preventing the ball from reaching complete rest. Any ideas?
     
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Have you confirmed that AddForce is not being called when there's no input? Comparing things to absolute zero with floats isn't safe. Ensure that you've not got crazy high gravity/gravity-scale or that the size of these objects is not huge. You said it's bouncing 1mm which is 0.001 world units.

    If you can, send me a project or more preferable would be a simpler reproduction case. In-fact, this'd probably be a good thing for you to do, just place something in the world with the same set-up and see if it exhibits the same behaviour.
     
  16. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Yep - I can confirm this as i've put in print statements to show it's only being called when I have the arrow button pressed down.

    Note: I have added in some extra code to stop the infinite bouncing problem but it's not ideal. The code goes like this:

    Code (CSharp):
    1.   void OnCollisionEnter2D(Collision2D collision)
    2.     {
    3.    
    4.         double vel = Math.Sqrt(Math.Pow(rb2d.velocity.x, 2) + Math.Pow(rb2d.velocity.y, 2));
    5.         print("velocity = " + rb2d.velocity + ", position = " + rb2d.position+", hyp = "+vel);
    6.         count = count + 1;
    7.         updateInfo();
    8.  
    9.        //sleepSpeed is a public float variable which specifies a speed that ball must be at for it to sleep.
    10.        //sleepHeight is a public float variable that specifies a height that the ball must be at before it sleeps.
    11.        
    12.         if (vel <= sleepSpeed && rb2d.position.y<=sleepHeight)
    13.         {
    14.             //print("I'm in here");
    15.             rb2d.Sleep();
    16.             count = 0;
    17.            // rb2d.AddForce(new Vector2(10,0));
    18.         }
    19.  
    20.     }
    Through experimentation, I figured out the that best values for sleepSpeed=2.4 and sleepHeight is around -11.
    Though, I need to figure out how to stop the ball naturally without this manual sleep.

    I've created a zip of my code - what is the best way for me to send it across?
     
  17. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    I have a question about LinearSleepTolerance & AngularSleepTolerance...

    I have been setting these parameters to various values, but it seems to have no effect.

    For example, I've set LinearSleepTolerance to 2.4.

    When my ball reaches a very slow velocity, such as (0.8,0.4), where the magnitude of the linear velocity is clearly less than 2.4, it continues to move around. Should the LinearSleepTolerance not cause it to fall asleep?

    Also, I've tried setting Angular Sleep Tolerance = 1, and then monitored the ball's angular velocity to see that even when angular velocity is around 0.5 or 0.8, the ball still does not sleep. Before you ask, the time to sleep is set to '1', so my expectation would be that it will sleep within 1 second once the conditions are satisfied.

    Sleep tolerance can be very useful, please explain how it's supposed to work.
     
  18. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    I'm kind of overwhelmed by the amount of problems you're hitting. Do you know that the physics engine we use is Box2D? Everything you're looking at is provided by and a basic bouncing collision coming to rest and sleeping takes no code so something else is going on here. If it's not sleeping then something is waking it up and it won't matter what your sleep tolerance is.

    I've shared this folder where you can dump a simple reproduction case but please try to reduce it down to the problem at hand. Either place it here or maybe put it on Google drive etc.
     
  19. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Hello everyone

    The good news for anyone who's facing this problem is that i've replicated the problem. Not only have I replicated it, I've experimented with various values to try narrowing down the exact conditions which gives rise to the problem.

    That bad news is that i've lost 2-3 hours of my life :(, but hopefully it will be worth it to help others and to save further time going forward.

    My zipped up project file can be found here: https://drive.google.com/open?id=1KuzDE8rHB9MVC74CG71fkx4HDbIaySxN

    Problem Description:
    I stumbled on a problem during Unity 2D Development where a ball when bouncing under gravity does not reach a state of rest or sleep but rather continues to bounce forever at a tiny speed.

    Details of Replication:

    I have created a new project which contains the following components:
    - 4 balls: yellow, blue, green, and red.
    - A background which has 2 walls and a floor.
    When you run the project, you will observe the blue and red balls do not stop bouncing, but the yellow and green balls do reach rest.

    Screen Shot 2019-05-28 at 12.54.16.png

    Analysis of the results

    In addition to the above, I experimented using several combinations of values to narrow down the cause of the problem. These are my findings:
    - For any combination of values that cause the problem, setting Collision Detection to 'Discrete' seems to correct the issue. Therefore problem is Isolated to 'Continuous' mode
    - A Gravity Scale value of 2 is needed to cause the problem. However, a Linear Drag value of 0.5 is also required when Gravity Scale is 2.
    - If the Gravity Scale is altered to 1.5 or 2.5, the problem no longer occurs and the ball stops bouncing.
    - For the red ball, if I alter the value of Gravity Scale to 1.999 the ball stops fine. If Gravity Scale is 2.2, the ball stops fine. If the gravity scale is 2.1 however, the ball bounces forever. Therefore, it seems like when the decimal precision approaches the value of 2 the problem is more likely to occur.

    I urge anyone to try this out in their environment and let me know of any solutions.
     
    Last edited: May 28, 2019
    pansoul likes this.
  20. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Try bumping up the velocity threshold in the 2D physics settings to 1.35+. This controls how Box2D deals with restitution (bounce) when performing contact solving as can be seen here. It uses this to decide when a collision should be inelastic or elastic.
     
    Alioz likes this.
  21. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    I don't understand what you mean by increasing the velocity threshold. What specific setting are you referring to and where is this setting on unity?

    Secondly, it sounds like you may not have downloaded & tried out my replicated environment (i could be wrong :)). I did take the effort to create the environment specifically based on your request. If you haven't, can you kindly try running my replication of this issue so that you can test your potential solutions to verify that they work?

    Many Thanks.
     
    Last edited: May 31, 2019
  22. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Go into the 2D Physics settings (as I said) and you'll see "Velocity Threshold". I thought you'd know about this, sorry if that wasn't the case. You can easily search for it using the API docs too. It's shown here in the manual.

    Why do you think that? I downloaded it and tried the above setting which solved the issue.
     
  23. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    Thanks for your very prompt reply! That was impressive ...

    So sorry, I made the assumption that you may not have seen my replication because the wording of the response sounded speculative starting with "Try bumping up the velocity threshold ... " which held a slight implication that it was a suggestion rather than a tried and tested solution :):).

    Forgive me for the misunderstanding - and thank you so much for running my replication and follow-up explanation. I will try it out now!
     
  24. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    No problem, was being concise. Pretty busy at the moment and a full-on cold ain't helping!

    I've noted this and will investigate further why it happens too. I was hoping that this setting can get you moving forward.
     
  25. mosh999

    mosh999

    Joined:
    Feb 22, 2019
    Posts:
    18
    WOHOO ... problem resolved! :):)
    I've set the threshold to a value of 2, which works well for highly bouncy values such as 0.9.

    I cannot believe how this one setting was the 'cure' to all the bounciness issues!

    MelvMay - thank you so much for your persistence and patience on this issue. Your contribution was massively useful - not only to me, but to many others who will encounter a similar issue.

    I'm very grateful for your assistance as I now have a clean and workable solution that can help me move swiftly onto the next stage of prototyping my game!
     
    pansoul and MelvMay like this.
  26. schashm3

    schashm3

    Joined:
    Oct 9, 2018
    Posts:
    10
    That was may problem too and it solved with your helps...thank you guys.
    just increase "velocity threshold" and that's it.
    thanks to mosh999 and MelvMay...
     
    MelvMay likes this.