Physics drag formula?

Hi there, i have this situation where i need to apply different forces to an object and then apply the gravity manually, but this gravity can't factor in the drag nor the mass of the object, meaning i want it to fall down as if the drag was 0 while not being set to 0 in the drag properties

right now i have this

rigidbody.AddForce(new Vector3 (0, -gravity * rigidbody.mass, 0));

this is enough to ignore the mass, but now i need to do some calculation to account for the drag of the object

i know unity uses physx but i can't find information anywhere how the drag calculation is done inside, even other poster formulas don't seem to work, all i know 0 means no influence and infinity means total influence

For a linear drag behaviour unlike real air pressure:

// Apply gravity
rigidbody.AddForce( Physics.gravity / _drag * Time.fixedDeltaTime, ForceMode.VelocityChange ));

Thats essentially what I do in uPhysics.


That can't be right, if drag is zero i get to divide by zero?

Just for the sake of it i actually tried it in a falling cube with a drag of 2 and this script next to a cube without any drag and the first one is slower

Like I said, its a linear behaviour.

As of the first being slower as the second, of course it is slower. Higher drag means more air friction, means less force/slower acceleration. In the above formular, 1 means no drag at all by the way.

Just to be accurate, this is a solution for drag, but prolly not the solution PhysX uses. Tho, when modelling physics in games it is not about pure correctness but about it looking good.

1 Like

In this case i need it to be 100% correct, i have other objects in the scene that use the normal physics and interact with this object, a linear drag from 0 to 1 doesn't work for me because this a situational case where i need to ignore the drag when falling down (other axis should have drag) so the object must fall down just like any other object around it

I only need to know the formula of how the drag is being used inside the unity, i'm not even sure if this is a physx thing or not because i can't find any explanation if i search for physx

Bumping this, any help would be appreciated

I can't believe this isn't documented somewhere, not even in nvidia physx documentation, i just need to know exactly how drag is being used, not a general way like "The higher the drag the more the object slows down." this doesn't help me at all

I finally got it working!!!!

I'm gonna explain in detail for future reference in case anyone needs it. I actually stumbled into the solution in a Cocos2D forum thread... ... ...yeah... o_o

This is how PhysX applies unity drag (or linearDamping as they call it) in pseudo code:

velocity = velocity * ( 1 - deltaTime * drag);

With that said, reverse engineering still took me a while, had to record values frame by frame and trial and error formulas till i got it right.

In my case i wanted to apply gravity without mass or drag so this is what i got now:

float veloc = rigidbody.velocity.y * rigidbody.drag;
float force = Gravity; //-9.81f
float coeff = (1 - Time.deltaTime * rigidbody.drag);

rigidbody.AddForce(new Vector3 (0, ((veloc + force) / coeff) * rigidbody.mass, 0));

If you want to apply as a velocity change you have to do it like this (note how mass goes away):

float veloc = rigidbody.velocity.y * rigidbody.drag * Time.deltaTime;
float force = Gravity * Time.deltaTime; //-9.81f
float coeff = (1 - Time.deltaTime * rigidbody.drag);

rigidbody.AddForce(new Vector3 (0, ((veloc + force) / coeff), 0), ForceMode.VelocityChange);

In theory you can use this to any force at any axis or all axis, in my case my force was gravity and i only wanted to remove drag from the y axis.

Cheers

19 Likes

Thanks for this kebrus. Me and you think alike. I'm surprised other people aren't as interested in this.

I've confirmed this still works the same in Unity 5.

If anyone else wants to play with the physics to get a better understanding for how it works, I have included a script that's basically a re-implementation of rigidbody force and drag.

using UnityEngine;
using System.Collections;


public class TransformDropTest : MonoBehaviour {

    public float mass = 1f;
    public float drag;
    public Vector3 acceleration = Vector3.zero;
    public Vector3 gravity = Physics.gravity;

    private int fixedUpdateTicks = -1;
    public bool atRest = false;

    void FixedUpdate() {

        //Stop moving if we're at rest.
        if (atRest)
            return;

        //Log debugging information
        fixedUpdateTicks++;
        Debug.Log (string.Format (
            "Fixed Update Ticks: {0}\n" +
            "Position: {1}\n" +
            //To derive velocity from acceleration, we need to divide by time
            "Velocity: {2}\n", fixedUpdateTicks, transform.position, acceleration.magnitude/Time.fixedDeltaTime));

        //Add the force
        AddForce (gravity, ForceMode.Acceleration);

        //Apply Linear Damping (drag)
        ApplyDrag ();

        //Move the object
        transform.position += acceleration;

    }

    void OnTriggerEnter() {
        atRest = true;
    }

    public void AddForce(Vector3 force, ForceMode forceType) {
        switch (forceType) {
        case ForceMode.Force:
            //Force mode moves an object according to it's mass
            acceleration = acceleration + force * mass * Time.fixedDeltaTime * Time.fixedDeltaTime;
            break;
        case ForceMode.Acceleration:
            //Acceleration ignores mass
            acceleration = acceleration + force * Time.fixedDeltaTime * Time.fixedDeltaTime;
            break;
        default:
            throw new UnityException("Force mode not supported!");
        }
    }

    //Apply Linear Damping
    public void ApplyDrag() {
        acceleration = acceleration * (1 - Time.deltaTime * drag);
    }
}
7 Likes

Sorry for bumping but I'm working on the same thing. I'm doing a racing game and I need something to limit the speed and thinking about applying drag. I'm looking for a formula that given the maximum Speed, the added drag will becomes larger with the velocity so that the acceleration cancel out and the car achieve stable max speed. Any help is appreciated.
Thank you very much and sorry.


The idea of knowing what unity is doing with drag was to intercept it to do something else. It's not to replace it entirely, you can do it anyway by putting drag and gravity at 0. This way you can do whatever you want with the object.

I know I'm not giving you ideas in how you can use something to your needs but maybe this topic is not what you need.

It isn't all lost tho, nickdas script above is a re-implementation of what unity does, you can use that as a base for what you want.

1 Like

Thanks kebrus. Your formula almost worked so i had to make a change. I'm using new formula:

void FixedUpdate()
    {
        float veloc = rig.velocity.magnitude * rig.drag;
        float coeff = (1 - Time.fixedDeltaTime * rig.drag);
        float force = (veloc / coeff) * rig.mass;

        rig.AddForce(transform.forward * force, ForceMode.force);
    }
1 Like

I wonder how the ForceMode.Impulse would be implemented in this example?

[quote=“jrmgx”, post:13, topic: 541279]
I wonder how the ForceMode.Impulse would be implemented in this example?
[/quote]

I’ve posted this answer quite some time ago where I explained all “force modes” in detail. You also might want to check out the two cross links at the bottom where I explain how to calculate the terminal velocity for a given drag, or how to calculate the drag for a certain terminal velocity

In this thread I’ve posted how drag works in Unity

2 Likes


I did a little wrong but I fixed it.

I implemented it but my object is still falling slowly, I'm not sure what I did wrong because I basically just copied the code:

  void ApplyGravity() // called during FixedUpdate
  {
    float vel = rb.velocity.y * rb.drag;
    float coeff = (1f-Time.fixedDeltaTime*rb.drag);
    float force = ((vel+gravity)/coeff) * rb.mass; // gravity = 9.81
    rb.AddForce(-Vector3.up*force, ForceMode.Force);
  }

Edit: I figured it out a couple minutes after posting, it's because I made gravity positive and was multiplying by -Vector3.up, but because I was adding rb.velocity.y it was inverted. After fixing it works fine now.