I am using rigidbody.AddForce() to move my player in FixedUpdate(), and I have noticed that “force added” → “object velocity” doesn’t scale linearly. So when I add a force of, let’s say 10, to the Z-axis, it will reach a velocity of 4 units/second after some time, but when I add half the force it doesn’t move at half the velocity, instead it moves at a speed much much slower.
I would like to be able to find the correct force to apply in order to accurately scale my speed up or down. I know an alternative is to use rididbody.velocity to execute movement or to clamp speed to a limit, but I would much rather be able to find the correct force to apply. So does anyone happen to know the correct formula necessary to achieve this, or maybe know of a way to make the force to velocity scale in a way I can accurately control it?
Edit: I am using Drag of 1 which is causing the scaling to not be linear, and I would prefer not to disable the drag because it makes sure my object doesn’t keep accelerating.
Are there any formulas that include drag? I think that might be what I need.
You might want to read my answer over here
In addition to my answer about how AddForce actually works, here’s how the drag is applied (at least in version 4.5.4f1):
velocity *= Mathf.Clamp01(1f - drag * Time.fixedDeltaTime);
You might want to read my post on the forum where i explain it a bit more in detail.
If you want to use Unity’s drag system, here are 6 helper methods to calculate:
- the final velocity you might reach for a given acceleration / velocityChange and drag value.
- the drag value required for a given acceleration / velocityChange to reach the desired velocity.
- the acceleration / velocityChange required to reach the desired velocity with a given drag value
You could extend each pair of methods to work with an actual force / impulse value. Keep in mind those methods only work for an acceperation / velocity change applied each FixedUpdate. One-time changes are pointless since you will have the final velocity at the moment you apply the force / acceleration / change. The drag will simply pull it back to 0.
float GetFinalVelocity(float aVelocityChange, float aDrag)
return aVelocityChange * (1 / Mathf.Clamp01(aDrag * Time.fixedDeltaTime) - 1);
float GetFinalVelocityFromAcceleration(float aAcceleration, float aDrag)
return GetFinalVelocity(aAcceleration * Time.fixedDeltaTime, aDrag);
float GetDrag(float aVelocityChange, float aFinalVelocity)
return aVelocityChange / ((aFinalVelocity + aVelocityChange) * Time.fixedDeltaTime);
float GetDragFromAcceleration(float aAcceleration, float aFinalVelocity)
return GetDrag(aAcceleration * Time.fixedDeltaTime, aFinalVelocity);
float GetRequiredVelocityChange(float aFinalSpeed, float aDrag)
float m = Mathf.Clamp01(aDrag * Time.fixedDeltaTime);
return aFinalSpeed * m / (1 - m);
float GetRequiredAcceleraton(float aFinalSpeed, float aDrag)
return GetRequiredVelocityChange(aFinalSpeed, aDrag) / Time.fixedDeltaTime;
Final note: In case a constant force is applied with a drag value > 0, the velocity will slowly get closer to the final velocity but won’t actually reach it. However due to floating point precision the remaining difference will usually be “rounded away” within seconds.
Also keep in mind that in case your drag value is greater than the fixed framerate, functions like GetRequiredAcceleraton will return infinity as there is no acceleration to reach the given speed.
There’s this guy called Newton? Maybe you’ve heard of him.
Anyway the correct formula is force = mass * acceleration.
There are lots of other formulas to try. Google Newtonian physics. Or classical physics.