Search Unity

PhysX rigidbody.drag bug?

Discussion in 'Physics' started by Cameron_SM, Dec 2, 2014.

  1. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    Seem to have come across a bug with how rigidbody.drag is applied.

    I was attempting to set a top speed and acceleration for an object and then calculate a drag value that would satisfy the top speed.

    Assuming rigidbody.drag is a Stokes drag (didn't seem to be quadratic) I'd have thought this would work:

    Code (CSharp):
    1. rigidbody.drag = (acceleration / topSpeed);
    2. rigidbody.AddForce(Vector3.right * acceleration);
    Which should work assuming velocity += (forces - drag * velocity) * dt

    But it doesn't, it's close but not quite. I tried the same manually (not using a rigidbody) and of course it works fine. Then I thought, what if unity is applying the drag after applying forces, that might explain the close-but-not-quite error I'm seeing from the drag value I'm using. To test this I set up the following:

    Code (CSharp):
    1. // Manual
    2. var topSpeed = 10f;
    3. var acceleration= 10f;
    4. var drag = (acceleration / topSpeed);
    5. velocity += Vector3.right * acceleration * Time.fixedDeltaTime;
    6. velocity -= drag * velocity * Time.fixedDeltaTime; // Velocity here is wrong?
    7.  
    8. //PhysX
    9. var topSpeed = 10f;
    10. var acceleration= 10f;
    11. rigidbody.drag = (acceleration / topSpeed);
    12. rigidbody.AddForce(Vector3.right * acceleration);
    13.  
    Both of these are identical step for step, and I'm fairly sure they're both incorrect too which would mean PhysX in Unity has a bug with how it applies drag. Feel free to correct me if I'm wrong though.
     
  2. MatthewW

    MatthewW

    Joined:
    Nov 30, 2006
    Posts:
    1,356
    I'd recommend manipulating the top speed yourself, either as rigidbody.velocity changes or via AddForce.

    Typically I build up something like a targetVelocity in my control scripts, and then apply it back to the rigidbody. My personal preference is to use ForceMode.Acceleration, which won't apply it instantaneously, but depending on the game you could use ForceMode.VelocityChange (I honestly know know what the difference is between VelocityChange in AddForce and just setting the rigidbody's velocity directly).

    I think it's clearer to apply drag yourself. You get the benefits of adding logic as needed--I often apply more drag if the desired velocity ends up more opposite of the current velocity, or different drags on different axes. A nice side benefit is that your tuning is more likely to survive the Unity 4.x -> 5.x physics transition, if that's something you expect in your project's schedule.
     
  3. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    I usually do what you suggest and actually just set rigidbody.velocity directly at the end of fixed update but was prototyping something new and ran into this little hiccup, though it worth sharing. I never quite understood what all the different force modes where either, setting the velocity explicitly meant I knew what I was getting. :)
     
  4. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    rigidbody.drag is applied during the next physics step I believe, so not really a bug just an inconvenience.
     
  5. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    Arr, that would also explain it, I'd still consider this a bug though, changes to rigidbody.velocity are applied in the current fixed step so the same behaviour should apply for all properties of rigidbody. Also, Rigidbody2D does not seems to have this problem. I would at least expect the two to behave the same and any properties being set on time managed objects that don't have an effect until the following frame to have very clear callouts in the documentation explaining that this is the expected behaviour.