How to determine velocity accurately

Hi all,

I recently started a project with the intention to master the physics aspect of Unity. Although I have a good knowledge of Unity, I never had the opportunity to work on game that makes extensive use of the physics engine. For that reason I’m trying to figure things out step by step;

So my first question is how to determine the final velocity of a rigidbody given a force over a stipulated time? My current setup is just a flat ground plane with a box collider and a cube with another box collider and a rigidbody. Both colliders have a custom physics material which has dynamic (i.e. kinetic) and static friction set to 0. The rigidbody has 0 drag and 0 angular drag. The cube has this script attached to it;

public class CubeController : MonoBehaviour {

    public float force = 10;
    public float time = 5;

    void Update()
    {
        if (Input.GetKeyDown (KeyCode.Space))
        {
            StartCoroutine(PhysicsCoroutine());
        }
    }

    // Use this for initialization
    IEnumerator PhysicsCoroutine () {
        Debug.Log ("Simulating");
        float t = 0f;
        while(t < time)
        {
            t += Time.fixedDeltaTime;
            rigidbody.AddForce(Vector3.forward * force);
            yield return new WaitForFixedUpdate();
        }

        float dynamicFrictionForce = collider.material.dynamicFriction * Mathf.Abs (Physics.gravity.y) * rigidbody.mass;
        float acceleration = (force - dynamicFrictionForce) / rigidbody.mass;
        float velocity = acceleration * t;
        Debug.Log (string.Format("[ACTUAL] Speed - {0}, Time - {1}", rigidbody.velocity.magnitude, t));
        Debug.Log (string.Format("[CALCULATE] Speed - {0}, Time - {1}", velocity, t));
    }
}

From basic physics formulas one can determine the following;

  • Fn = M * G * cos(O) where Fn is the normal force, M is mass, G is gravity and O is the angle of inclined surface
  • Fk = Fn * Uk where Fk is the kinetic friction force, Fn is the normal force and Uk is the coefficient of the kinetic friction
  • F - Fk = M * A where F is force, Fk is the kinetic friction force, M is mass and A is acceleration
  • V = U + AT where V is the final velocity, U is the initial velocity, A is acceleration and T is time

Therefore given the following values we can find the final velocity;

  • M = 5
  • F = 20
  • T = 5
  • Uk = 0
  • G = 9.81
  • O = 0

Fn = 5 * 9.81 * cos(0)
= 49.05

Fk = 49.05 * 0
= 0

From equation 3 we can find the acceleration by (F - Fk)/M;

A = (20 - 0)/5
= 4

V = 4 * 5
= 20m/s

Therefore the velocity is 20m/s, which matches the magnitude of the rigidbody’s velocity. However when I change just the dynamic friction in the custom physics material, I get incorrect results. Assuming all values remain the same except Uk which is now 0.1

Fn = 5 * 9.81 * cos(0)
= 49.05

Fk = 49.05 * 0.1
= 4.905

A = (20 - 4.905) / 5
= 3.019

V = 3.019 * 5
= 15.095

But the rigidbody.velocity.magnitude is 10.24. Why there is this difference? Is there anything wrong in my formulas? How can I accurately predict an object velocity?

Your help is greatly appreciated,

Yours truly,
A physics noob :slight_smile:

Anyone?

Anyone?

been years since college doing any mechie physics stuff. but i thought id chip in a bit.
not been through the equations as yet, dont have my old college notes, but have a look through

some interesting stuff.
and

might get some more info from there. sorry cant be of any further help at the mo.

If you go here:

You’ll see the 4 force modes. And if you click each you’ll see the formula they use for each. They are as follows:

Force:
force = mass * distance / time^2

Acceleration:
acc = distance / time^2

Impulse:
impulse = mass * distance / time

VelocityChange:
vel = distance / time

You can see my implement my own versions of AddForce to simulate similar functionality to ‘AddForce’ here:

            public void AddForce(Vector3 f, ForceMode mode)
            {
                switch (mode)
                {
                    case ForceMode.Force:
                        //force = mass*distance/time^2
                        //distance = force * time^2 / mass
                        this.Move(f * GameTime.DeltaTime * GameTime.DeltaTime / _mass);
                        break;
                    case ForceMode.Acceleration:
                        //acceleration = distance/time^2
                        //distance = acceleration * time^2
                        this.Move(f * (GameTime.DeltaTime * GameTime.DeltaTime));
                        break;
                    case ForceMode.Impulse:
                        //impulse = mass*distance/time
                        //distance = impulse * time / mass
                        this.Move(f * GameTime.DeltaTime / _mass);
                        break;
                    case ForceMode.VelocityChange:
                        //velocity = distance/time
                        //distance = velocity * time
                        this.Move(f * GameTime.DeltaTime);
                        break;
                }
            }

Note, I resolve the formula for ‘distance’, as I want to calculate the distance to move as if that force was applied.

With those you could get the velocity, which would really just be the distance traveled over some set time (in unity this is usually per second). But of course because this would not actually be accurate because the velocity is determined discretely over a series of updates per second (it attempts a fixed number of them, but of course has minor error, and there is the ever prevalent ‘float error’).

The best way to get the most accurate then is to perform a summation of the number of ‘ticks’ of addforce you’ve done to calculate a more accurate distance over a duration of time and then adjust that to your velocity scale.

So if you added a force 10 times in a row, every 1/60th of a second. That’d be sum up the distance 10 times, then multiple by 6 (60/10) to get the velocity as units per second.

1 Like

Hey guys,

Thanks for your replies. I will go through them carefully when I get home. Here is a summary of what I concluded so far.

After I experimented a bit more with the equations, I found out that I get more accurate results by multiplying the dynamic friction force by 2. In the previous example, those would be calculated as follows;

Assuming all values remain the same except Uk which is now 0.1

Fn = 5 * 9.81 * cos(0)
= 49.05

Fk = 49.05 * 0.1 * 2 (notice the * 2 here)
= 9.81

A = (20 - 9.81) / 5
= 2.038

V = 3.019 * 5
= 10.19

The rigidbody.velocity.magnitude is 10.24, which now matches the calculated one (expect for a small error). What I can’t figure out is where that * 2 comes from! I couldn’t relate it to any physics formula! Anyone from the Unity team is reading this? Maybe you can indicate how the friction is being calculated when force is being applied. I couldn’t find any details on the Physx SDK docs.