Search Unity

Stop a rolling sphere on inclined surface

Discussion in 'Scripting' started by unikum, Oct 23, 2011.

  1. unikum

    unikum

    Joined:
    Oct 14, 2009
    Posts:
    58
    Anyone know how to implement rolling friction or fake it so a ball/sphere can stop in the middle of an inclined surface? Using drag just makes it slow down, but doesn't stop unless the surface is flat. I need to simulate how a golf ball rolls on the grass, and like in real life it has to be able to stop rolling even if it's not a completely flat surface (depending on grass height/green softness).

    I have tried to understand rolling friction, but I don't understand how to implement it in Unity. Really appreciate if anyone know how to solve this.
     
  2. cgf

    cgf

    Joined:
    Oct 16, 2011
    Posts:
    25
  3. unikum

    unikum

    Joined:
    Oct 14, 2009
    Posts:
    58
    Thanks cgf, but just multiplying the velocity like in that thread doesn't give me a very good result.

    I think I might have come up with a solution that works OK. My code is a mess at the moment, but I'm pasting the vital parts for future reference for other people. But if anyone know a better solution, or see that something with the code is completely wrong, please point it out. I have this code in the fixed update in my golf ball class.

    What it does is calculate the rolling resistance force and then applying that force in the opposite direction that the ball is traveling. If the velocity of the ball is lower than the resistance, the ball sleeps. Does it makes sense to use the fixedDeltaTime like I do? Or is it just a coincidence that it works? I'm not good with this stuff.

    Code (csharp):
    1.  
    2. // the rolling resistance coefficient depends on materials. I'm using ~0.05f in my tests.
    3. // can combine with drag too. Setting the Coefficient to around 0.08 makes the ball stop
    4. // in a 2-3 degree slope. 0.05 and it can stop in a 1 degree slope. Longer grass would have
    5. // much higher value and the ball will stop in steeper slopes.
    6.  
    7. if (Physics.Linecast(transform.position, transform.position - new Vector3(0, radius*2, 0), out hitInfo))
    8. {
    9.    float rollingFriction = (rollingCoefficient * mass * (Physics.gravity.y * -1) * Mathf.Cos(Vector3.Angle(hitInfo.normal, Vector3.up)));
    10.    if (rollingFriction < 0)
    11.       rollingFriction *= -1;
    12.  
    13.    if (rigidbody.velocity.magnitude  > rollingFriction * Time.fixedDeltaTime)
    14.    {
    15.       var vel = new Vector3(Mathf.Abs(rigidbody.velocity.x), Mathf.Abs(rigidbody.velocity.y), Mathf.Abs(rigidbody.velocity.z));
    16.       var toOne = 1 / Mathf.Max(Mathf.Max(vel.x, vel.y), vel.z);
    17.       rigidbody.AddForce((rigidbody.velocity * toOne) * -rollingFriction);
    18.    }
    19.    else
    20.    {
    21.       rigidbody.Sleep();
    22.    }
    23. }
    24.