- Home /
Spherical rigid body will never stop rolling regardless of drag
My problem is that I have a rigid body with a spherical collider and once it starts moving (rolling) it never stops.
I have read other answers here which state that changing the drag (angular and normal) is the answer to this problem but I must be doing something wrong somewhere else. I have been experimenting with this for hours and cant find a solution.
I have moved the drag to a million, still moves but very very slowly. I have moved the angular drag to a million with similar results. I have set the sleepThreshold to a high number. This didnt seem to do anything. I tried changing the friction on the terrain.
I placed the ball on a flat, horizontal plane for all of these tests and applied an impulse to start it moving. It has never come to a stop yet.
There are times when it reaches a certain velocity and then stutters like it is about to stop and then it starts moving at a constant velocity forever, I think I can visibly observe the shift from deceleration to constant velocity. It doesnt make any sense to me at all.
It is my assumption that the ball should stop eventually and that unity, being so advanced, would handle this easily but its possible that I'm missing something due to being so new.
I just tested this and got the same results. If gravity is turned off for the rigidbody, then both linear and angular momentum will stop with drag. However, if the sphere is rolling on a level plane with gravity on, then it won't.
If no one here comes up with an answer, then I'd suggest filing a bug report.
Hi,
If you come up with a solution, please post/let me know. I'm trying to simulate a golf ball rolling on a flat surface (putting green) and like you say it slows down, but never stops rolling. The only thing I've tried that somewhat works is inside OnCollisionStay increase both drag and angularDrag by some amount. However, this approach just feels wrong and I'd have to reset the values once the ball stops rolling completely, otherwise it won't roll at all if I push it again. Thanks.
Has anyone come up with a solution for this? I have the same problem and spent a whole day trying to fix this without success.
When it hits that constant velocity point simply manually reduce its velocity.
Yes, obviously I am aware that I could do this manually, but I could also handle gravity manually, and drag and collisions etc. To me, the whole point of using a sophisticated engine is that it handles this sort of thing so I don't have to do it manually. $$anonymous$$y question basically comes down to, is there a way for unity to handle this simple physics properly, and if not, why not?
Ok, I totally understand. It is frustrating when things like this happen.
It seems a lot worse when long term bugs are overlooked.
@majellin Found a solution that actually works. Updated my answer.
Answer by meat5000 · Apr 15, 2016 at 12:36 PM
To offer a workaround, simply apply your own opposite force proportional to the actual velocity of the sphere. It only needs to be small. It is basically simulating drag. It will ensure that at all velocities there is a reaction force. This guarantees to slow down the rigidbody over time.
When it is a fraction of the velocity when velocity is 0 the opposite force will also be zero, so no force will be applied and the ball wont start randomly rolling off.
As @Majellin states "This shyet shouldn be happenin, yo". And he's right.
EDIT: Using the above theory didnt make the rigidbody stop rolling, but I did eventually find a way to make it stop.
By default the inertiaTensorRotation
is set to Quaternion(0,0,0,1). simply changed this value to something small; Quaternion(0.01, 0.01, 0.01, 1) and the damnable thing stopped, with the aid of my snippet.
#pragma strict
var rb : Rigidbody;
var scaler : float = 0.1;
function Start ()
{
rb = GetComponent(Rigidbody);
rb.sleepThreshold = 0.01;
}
function FixedUpdate ()
{
//Debug.Log(rb.angularVelocity.x + " : " + rb.angularVelocity.y + " : " + rb.angularVelocity.z);
rb.inertiaTensorRotation = Quaternion(0.01, 0.01, 0.01, 1);
rb.AddTorque(-rb.angularVelocity * scaler);
}
I had initially placed rb.inertiaTensorRotation =
inside the Start() function but realised that the value was being reset to 0 every frame. I had to move this to the loop so it was set to a value just before I made each AddTorque call. Actually, spamming the rb.inertiaTensorRotation was enough to make the ball stop on its own.
Perhaps I found the bug here.
Try it and see if it works for you!
I'm surprised that there isn't a real fix for this yet. I just started with Unity this week, do you have any code snippet for that?
Hey @meat5000. That was a huge help!
Initially, I was getting a weird effect as if the sphere was shaking but then I tweaked the values on the scaler, friction and drag on the sphere to achieve what I was ai$$anonymous$$g for. I also made it so this forced friction would act only when the ball was on the ground and when it was at constant speed.
Thank you sir!
$$anonymous$$ost welcome. If you turn the scaler up super high you get the total strangeness of the ball rotating on the spot :D Demonstrates the brokenness of the sphere rigidbody in Unity :D
I think the TensorRotation should be worked out based on the movement of the Sphere. I believe its self modifying like Velocity. When I jammed in that random value it offset that point making it act like an unbalanced wheel; but it is this Asymmetry that makes it stop.
Why not just use rb.angularDrag
ins$$anonymous$$d of a separate variable. You are simulating drag after all. Using if for something else would be weird, but here I believe it fits.
Answer by Oliver-Bogdan · Oct 03, 2016 at 02:58 PM
I had this issues as well and after spending some time we have discovered that constantly setting the rigidBody.mass for the sphere at the start of FixedUpdate makes this problem go away.
Had to register just to thank you for posting this, so simple yet so effective.
Answer by HotPhone · Dec 07, 2016 at 10:31 AM
I fixed the problem by setting angular drag to around 5.,I fixed the problem by setting the angular drag to 5. drag is 0.
Now the ball behaves normally, it stops when rolling after a time.
EDIT: It still rolled with a very very low velocity for ever. I added this code to make it stop.
void FixedUpdate () { if (rigid.velocity.magnitude < 0.1f) rigid.velocity = Vector3.zero; }
There's a "Sleep Threshold" in the Physics $$anonymous$$anager that might take care of this problem, if the value is high enough.
Answer by aditya · Apr 15, 2016 at 12:06 PM
There could be two reasons, either your ball is not using Gravity
or it is Kinematic
... if these two reasons are not what making your BALL
moving constantly, then possibly your are constantly applying the ADDFORCE
in Update
or FixedUpdate
... OR YOU'VE APPLIED A PHYSICS MATERIAL WITH NO DRAG
Thanks for the reply. The ball is not kinematic and it is using gravity. I know this because it does other physics including gravity before the nonstop rolling. I also am not adding any forces after the initial impulse and the physics material does have dra because the ball does slow down initially, it just doesn't stop.
then will you pls send us your code snippet and a screenshot while your object with rigidbody selected as i wanna take a look at your INSPECTER
Replicating this bug needs no code. Just make a terrain or plane and start a sphere with rigidbody rolling on it.
To fill you in on this, it seems that the velocity is reduced to a $$anonymous$$imum depending on the angular drag but this factor only seems to apply to the initial velocity as the sphere never stops.
If you place a Physic $$anonymous$$aterial on the Terrain you get the warning
"TerrainColliders can no longer act as triggers since Unity 5.0"
But it doesnt matter because even if you put a high friction physic material on the sphere and a plane it still never stops.
It was one of the early bugs of the engine and yes, it is totally surprising they havent fixed it yet.