velocity, mass and damping

How can I replicate correctly a damping force (like Rigidbody.drag but without effecting the gravity axis)

// for 100% drag
Vector3 vel = aRigidBody.velocity;
vel.y = 0;

aRigidBody.AddForce( -vel * aRigidBody.mass * Time.deltaTime );

Obviously I’m not properly understanding what’s going on with force calculations, and while a solution for this would be fantastic, what would really be appreciated would be an explanation.

I’m assuming 1 unit of distance in Unity is 1 Metre, and 1 unit of mass in Unity’s Rigidbody.mass is 1KG, if that is a sane assumption what is 1 unit of Unity velocity ?

There is a discussion on this and a posted solution in Physics drag formula?

Your assumptions are correct and velocity is in metres per second (m/s).

Whilst you can code a separation from gravity effects, in the real world drag will affect falling just the same as horizontal directions of motion. However, as I’m sure you are aware, the drag factor in the rigidbody is not representative of real world aerodynamic drag on the object (for this you would need to set rigidbody.drag = 0 and code your own), it is really just a way to stop objects moving forever once acted upon.

The main reason I’m implementing drag like this is so my player character doesn’t drift when turning like a hovercraft you can be thrusting and facing perpendicular to the direction of travel for a little while before direction changes, I’ve found with a camping force balanced with thrust the it gives a less hovercraft effect but if you just use the drag property or effects falling too… Thanks for the link I’ll check it out now.

If you wanna do a simplified version of drag that works on different axis you can check this out, it’s for a 2D racer but you can use the same logic for whatever you want.

oh dear think I’m more confused

oh dear think I’m more confused now…

with a drag of 1.0 the player shouldn’t be able to move (ie 100% drag)

I had to modify the code as it was only adding drag to the Y axis (the opposite of what I want)

this seems to make such a force but not 100% drag

    public float drag = 1f;
 
    // from the manual "For reading the delta time it is recommended to use Time.deltaTime instead because it
    // automatically returns the right delta time if you are inside a FixedUpdate function or Update function."
    void FixedUpdate()
    {
        // not understanding big magic numbers 20f and 24!
        // mass = 100kg
        // drag = 1 (100% shouldn't be able to move, except jump?)
     
        rb.AddForce(transform.forward * 20f * Input.GetAxis("Vertical") * Time.deltaTime, ForceMode.VelocityChange);
        rb.MoveRotation(Quaternion.Euler(0, Input.GetAxis("Horizontal") * 300f * Time.deltaTime, 0) * rb.rotation);
     
        cooldown--;
        if (Input.GetButtonDown("Jump")  && cooldown < 0) {
            cooldown = 30;
            rb.AddForce(transform.up * 24f * Time.deltaTime, ForceMode.VelocityChange);
            Debug.Log("jump " + Time.time+ "  "+Time.deltaTime);
        }

        // simulate drag, but without effecting gravity...
        Vector3 v = -rb.velocity;
        v.y = 0;

        Vector3 veloc = v * drag * Time.deltaTime;
        Vector3 force = veloc * Time.deltaTime;
        float coeff = (1 - Time.deltaTime * drag);

        rb.AddForce((veloc + force) / coeff, ForceMode.VelocityChange);
    }

Where’d you get that?
even in the docs page they set an example value of 20: https://docs.unity3d.com/ScriptReference/Rigidbody-drag.html
so that alone must mean it’s not just normalized “drag percentage”, or whatever you think it is.

if you feel brave take a gander at the nvidia physix docs, but be warned - it’s highly confusing to “regular” people(me included, i’m the embodiment of the “I have no idea what i’m doing” dog on pc meme)

Did you follow the thread to https://forum.unity.com/threads/drag-factor-what-is-it.85504 ? It is quite a long read, but ultimately revealing, especially the post by S_Darkwell.

If you are writing this as a rigidbody controller I suggest you have a think about exactly how you want it to behave. I am going to guess that playing with a drag force is not the answer - unless it really is something that is significantly braked by fluid drag forces.

If the rigidbody is kinematic (its motion is not influenced by other mobile rigidbodies), then check out Rigidbody.MovePosition and MoveRotation. But you will have to code your own gravity effect on motion.

If the rigidbody is not kinematic (i.e. its motion is only defined by the forces acting upon it), then you must carefully consider how the forces to move, stop and turn the body are applied. If this is for human like character motion, this is not trivial. For example, if your current system is hit by a boulder and knocked flying, it will in fact rapidly stop due to the drag. You will need to control motion by carefully constructed forces.

yes I did read the link, and thank you for supplying it, at first it didn’t seem terribly pertinent however with a little fettling I now have a rigid body working how I like, it can go up (and down) stairs (actually an invisible ramp), jump and works with a multi waypoint kinematic platform too

The controller code is actually less than 80 lines including comments, the values used for forces look much more sane too…

I have a corner case to work out to do with handling edges, but I’m confident the solution for this will be simple (I have one in mind already)

here is a list of the values I’m currently using in the editor

                                        // rb mass = 80
                                        // rb drag = 0f
                                        // rb Angular drag = 16f
   
    [SerializeField]                    // resistance to movement
    private float drag              =   0.1f;
    [SerializeField]                    // force applied to player when moving forward
    private float forwardForce      =   55.0f;
    [SerializeField]                    // how quickly the player turns (not a force)
    private float turnFactor        =   300f;
    [SerializeField]                    // ensure intermittent multiple input events are ignored
                                        // also terminates the jump
    private int jumpCoolDown        =   50;
   
    [SerializeField]                    // upward force applied when jumping
    private float jumpForce         =   200.0f;
    [SerializeField]                    // forward force applied when jumping
    private float jumpFrdFactor     =   0.7f;
    [SerializeField]                    // for handling going down ramps
    private float stepHeight        =   0.2f;

much, much happier with it all now! (thanks!)