Calculating Velocity from AddForce and mass

Does anyone know how to calculate the velocity of an object of a given, constant mass after using AddForce? There is no resistance on the rigidbody, and the use gravity box is unchecked (doesn’t use gravity from the physics engine).

Ive tried looking for actual physics formulas, but they seem to all need acceleration or the length of time that the force is applied. The way I understand it, AddForce is an instant, one-time force, and doesn’t have a length of time associated with it. If AddForce is actually applied over a length of time, that information will be just as helpful as a formula.

Thanks

1 Like

All I can suggest is use delta position.

The problem is, I need to calculate what the objects velocity will be, before it starts moving. This rules out calculating its velocity with distance and time.

1 Like

The AddForce() function assumes that the force is applied over the fixed timestep duration set by the Unity engine. By default, the fixed timestep is set to 0.02 seconds, but you can change it to almost anything you want in the Time Manager settings which is accessed in the Edit->Project Settings->Time menu. You can also get or set the fixed timestep in code via Time.fixedDeltaTime.

Deriving the change in velocity is a simple matter of solving F=ma for velocity…

F = ma
a = v/t = F/m
v = at = (F/m)t

Velocity (v) equals Force (F) divided by mass (m) multiplied by time (t).

C#

   float v = (F/rigidbody.mass)*Time.fixedDeltaTime;
19 Likes

That post goes above and beyond! The fixed timestep told me exactly what I needed, but you took it a couple steps further for me. Thanks!

2 Likes

Code correction. I used Time.fixedTime in the code example, which is incorrect since this is the elapsed time since the program started. You want to use Time.fixedDeltaTime.

Ok, I re-arranged a few things about how I was applying the formulas and got it coded, but I’m running into another problem that doesn’t make sense.
Some background:
To setup my project, i have made a to-scale (almost) model of the earth, the sun, and the moon. This was done so that I would have numbers to reference to for my math, to make sure everything is working right
When I Debug.Log the NeedVel, it shows the correct velocity (29846m/s). The NeedForce value is really high but given the scale and numbers involved, that didnt really seem out of place. Now I’m starting to wonder becuase the earth and moon go shooting off in the direction the starting force is applied and reach scientific notation values in the transform.position almost instantly. I have included the 2 scripts involved. Is this a code problem, math problem, or typo problem?

Pull.js:

#pragma strict
//**************************************************
//This script goes on the object with the most mass.
//**************************************************
//Set Gravational Constant. use this for time scaling.
static var Gcons : float = 0.000000000067;
function Start () {

}   

function Update () {
	var obj1 : GameObject;
	var obj2 : GameObject;
	var SolarBody : GameObject[] = GameObject.FindGameObjectsWithTag ("Solar");
	var dist : float;
	var gforce : Vector3;
	var i : int;
	var j : int;
	for (j=0;j<SolarBody.length;j++){
		for (i=j+1;i<SolarBody.length;i++) {
			//Assign objects to be gravitized.
			obj1=SolarBody[j];
			obj2=SolarBody[i];
			//Get distance between objects
			dist = Vector3.Distance(obj1.transform.position,obj2.transform.position);
			//Calculate force of gravity
			gforce = Vector3.Normalize(obj2.transform.position - obj1.transform.position)*Gcons*obj1.rigidbody.mass*1000000000000000*obj2.rigidbody.mass*1000000000000000/(dist*dist)*Time.deltaTime;
			//Apply Gravity
			obj1.rigidbody.AddForce(gforce);
			obj2.rigidbody.AddForce(-gforce);
		}
	}
}

OrbitStart.js: I’m thinking the problem is line 64

#pragma strict

//**********************************************
//This script goes on all 'Solar' tagged objects
//except for the object with the highest mass.
//**********************************************

function Start () {
	var OrbitTarget : GameObject;
	var obj1 : GameObject;
	var obj2 : GameObject;
	var CentralObject : GameObject;
	var SolarBody : GameObject[] = GameObject.FindGameObjectsWithTag ("Solar");
	var dist : float;
	var gforce : Vector3;
	var gforce1 : Vector3;
	var gforce2 : Vector3;
	var i : int;
	var NeedVel : float;
	var NeedForce : float;
	//Find the object with the highest gforce with this object
	for (i=0;i<SolarBody.length;i++) {
		if (OrbitTarget!=null){
			if(SolarBody[i]!=gameObject){
				if (OrbitTarget!=SolarBody[i]){
					obj1=gameObject;
					obj2=SolarBody[i];
					dist = Vector3.Distance(obj1.transform.position,obj2.transform.position);
					gforce1 = Vector3.Normalize(obj2.transform.position - obj1.transform.position)*Pull.Gcons*obj1.rigidbody.mass*1000000000000000*obj2.rigidbody.mass*1000000000000000/(dist*dist)/2*Time.deltaTime;
					dist = Vector3.Distance(obj1.transform.position,OrbitTarget.transform.position);
					gforce2 = Vector3.Normalize(OrbitTarget.transform.position - obj1.transform.position)*Pull.Gcons*obj1.rigidbody.mass*1000000000000000*OrbitTarget.rigidbody.mass*1000000000000000/(dist*dist)/2*Time.deltaTime;						
					if (gforce1.magnitude>gforce2.magnitude){
						OrbitTarget=SolarBody[i];
					}
				}
			}
		}else{
			OrbitTarget=SolarBody[i];
			if(SolarBody[i]!=gameObject){
				if (OrbitTarget!=SolarBody[i]){
					obj1=gameObject;
					obj2=SolarBody[i];
					dist = Vector3.Distance(obj1.transform.position,obj2.transform.position);
					gforce1 = Vector3.Normalize(obj2.transform.position - obj1.transform.position)*Pull.Gcons*obj1.rigidbody.mass*1000000000000000*obj2.rigidbody.mass*1000000000000000/(dist*dist)/2*Time.deltaTime;
					dist = Vector3.Distance(obj1.transform.position,OrbitTarget.transform.position);
					gforce2 = Vector3.Normalize(OrbitTarget.transform.position - obj1.transform.position)*Pull.Gcons*obj1.rigidbody.mass*1000000000000000*OrbitTarget.rigidbody.mass*1000000000000000/(dist*dist)/2*Time.deltaTime;						
					if (gforce1.magnitude>gforce2.magnitude){
						OrbitTarget=SolarBody[i];
					}
				}
			}
		}
	}
	//Assign objects to be started.
	obj1=gameObject;
	obj2=OrbitTarget;
	//Get distance between objects
	dist = Vector3.Distance(obj1.transform.position,obj2.transform.position);
	//Determine the velocity needed for orbit.
	Debug.Log(obj1.name);
	NeedVel = Mathf.Sqrt(obj2.rigidbody.mass*1000000000000000*Pull.Gcons/dist);
	Debug.Log(NeedVel);
	//Determine Force needed to reach that velocity
	NeedForce = obj1.rigidbody.mass*1000000000000000*(NeedVel/Time.fixedDeltaTime);
	Debug.Log(NeedForce);
	//Get the direction of gravity's force
	gforce=Vector3.Normalize(obj2.transform.position - obj1.transform.position);
	//Apply the Needed force perpendicular to gravity's force
	rigidbody.AddForce(Vector3(gforce.z,gforce.y,gforce.x)*NeedForce);
}

function Update () {

}

EDIT: While it shouldn’t effect the calculations (as demonstrated by the accurate NeedVel value), the “*1000000000000000” might need some clarification as to why its there. That is the ratio of the scale of distance and mass. If you use the same scale for both, no matter the scale, something ends up out of the bounds of the numbers Unity can handle.

Slight bump and an update.

Man, the action of this code keeps getting stranger and stranger. Changing Gcons does the opposite of what you would expect for some reason. Increasing it SHOULD increase the amount of force from:

            gforce = Vector3.Normalize(obj2.transform.position - obj1.transform.position)*Gcons*obj1.rigidbody.mass*1000000000000000*obj2.rigidbody.mass*1000000000000000/(dist*dist)*Time.deltaTime;
[/CODE}
Obvious right? Its on the top of the fraction, thus, an increase in it should increase the overall value, but in fact, it does the opposite. What is going on with these scripts? Something is SERIOUSLY wrong. My eyes and the unity error checking/reporting system both come up empty, No errors, and the formulas seem correct.

I am using the following formulas, on the respective lines:

Pull:27 - F=(G*M1*M2)/d^2  <Force of gravity between 2 objects>
F=Force of gravity
G=Gravitational Constant
M1 and M2= Mass of the 2 objects
d=Distance between objects

OrbitStart:61 - V=sqrt(MG/d) <Orbital Velocity of an object when the masses are significantly different>
V = Velocity
M = Mass of the heavier object
G = Gravitational Constant
d = Distance between objects

OrbitStart:64 - F=MA=M(V/t) <Basic Force equation>
F = Force
M = Mass
A = Accelleration
V = Velocity
t = time

Anyone have any ideas?

Hey folks. My first post.

I’ve recently ran into the very same problem.
I had to “imitate” Unity physics in manual (isKinematic = true) mode.

AddForce(…, ForceMode.Force) is advertised as an “immediate” action.
However we do know, that in order to really change velocity of a rigid body a certain force needs to work for some time. It’s not even physics, but simple math where acceleration (and thus force) is a derivative function of velocity taken by time:

F(t) = m * a(t) = m * V’(t)

Force as a velocity changer does not make any sense without time. It needs time. Force applied instantly (kind of “for zero point zero seconds”) will not have any effect over velocity at all. End of story.

So knowing this, and (partially) agreeing with Brian Stone we do guess, that there needs to be some time to be taken into account. What would one use to perform an immediate physical action? Well, the assumption is logical and simple, it’s Time.fixedDeltaTime. However I’ve ran some “scientific poke with calculator” tests by removing all the side effects like drag (for God’s sake, Unity developers, why didn’t you call it air friction or something?) and gravity, and it appears, that velocity is calculated as if the fixed time delta was either not taken into account at all or simply was equal to 1 SECOND (this is where I allow myself to not agree with Brian Stone). On purpose have I played with different fixed time deltas and result stays the same.

So, to imitate the AddForce(…, ForceMode.Force) behaviour yourself, one should do this:

Vector3 force = new Vector3(1.0f, 0.0f, 0.0f);

gameObject.rigidbody.isKinematic = true;
gameObject.rigidbody.velocity = 1.0f * force / gameObject.rigidbody.mass; // Where 1.0f is 1 second

The reason why you have reached 1.0 conclusion in your tests is that time is not being used in AddForce at all. It is not real world physics where you indeed need time for any force to take effect, remember that it is only a simplified simulation. You can change the velocity immediatelly, because you are only changing the value of a single vector in the simulation, not actually taking time to push an object.

thank’s a lot for the example! I was trying to use corroutines, weird algorithms using time… the formula above is the deal, I just didnt realize how to translate the formula into Unity.

Hello,
you have some problems because of some misconceptions about Force, Acceleration and Velocity.

Let’s start with Force. What is a force? It’s a push or pull. Simple as that :). If ONLY one force is applied ONCE (only one time, for a really small moment) to an object with
NO FORCES acting on it, this object gets pushed or pulled. The force, when applied, gives it velocity. Now, it has velocity, and no forces are acting on it - because
we applied ONLY ONE FORCE ONLY ONCE (for a tiny moment). At the moment we applied the force, the object gained some velocity, it had acceleration in that moment - from 0 to v (where “v” is the current velocity).
Now it does not have any acceleration.

When there are no forces acting on an object, there is no acceleration or deacceleration - and the object won’t change it’s velocity.
There is nothing stopping it from moving, and there is nothing accelerating it. It will move with it’s velocity forever.
It will ONLY stop when we apply a counteracting force on it (in the opposite direction of the moving object).

But what will happen if we apply a force continuously to it? Well, it will have acceleration. Why?
OK, we apply force for the first time to the object that is NOT MOVING (doesn’t have velocity) and NO FORCES are acting on it. It is pushed by the force, so it get’s some
velocity. But now we apply the force again (we are applying it continuously). The object has some velocity, and when we apply the same force again, it gets pushed again, so it gains more velocity.
When we continue to apply the same force it gains more and more velocity - it has acceleration.

That’s why the formula is
F = m*a,
where “F” is force, “m” is mass and “a” is acceleration.

The WRONG formula is
F = m*v,
where “v” is velocity, because it can have velocity when no forces are currently applied to it.

If we have NO ACCELERATION, we aren’t applying any force, and it doesn’t matter if it HAS or HAS NOT velocity.

In your case, you want to calculate what force is needed to accelerate a stopped object to a given velocity. So,

F = m*a
a = dv/dt, where “dv” is deltaVelocity.
dv = (v - v0), where “v0” is the velocity in the beginning (in our case v0 = 0, because the object is not moving), “v” is the end velocity (in our case the desired velocity).

So,

a = (v-v0) / dt, where “dt” is the time it took the velocity to change from v0 to v (in fact, dt = t - t0, t = end time, t0 = starting time. For example, if the change
happened in the timeframe between 2 seconds and 3 seconds, dt will be t - t0 = 3 - 2 = 1 second).

In our case, t0 = 0s, because it’s from the start => so our formula now is
a = (v - v0) / (t-t0)
a = (v - 0) / (t - 0)
a = v/t (this is ONLY BECAUSE v0 = 0 and t0 = 0)
F = m*(v/t)

Now, as Brian Stone said,
The AddForce() function assumes that the force is applied over the fixed timestep duration set by the Unity engine.
By default, the fixed timestep is set to 0.02 seconds, but you can change it to almost anything you want in the Time Manager settings
which is accessed in the Edit->Project Settings->Time menu. You can also get or set the fixed timestep in code via Time.fixedDeltaTime.
Well, then “t” from the formula is the fixed timestep duration set by the Unity engine in our case,
t = Time.fixedDeltaTime.

So, finally

F = m * (v/t), where “m” is the mass of the object, “v” is the desired velocity and t = Time.fixedDeltaTime.

I hope this helped you reader, I hope I explained it as simple as it can be.

11 Likes

Yall seem like the people to ask about acceleration and deceleration. I am trying to make a top down 2d soccer game with a ball that will continue to roll after the player stops. I can’t seem to figure out the phisics without having gravity. I don’t need anything fancy, I just need slowed deceleration with collision. Thanks