Setting Local Velocity Of A RigidBody

I’m currently using this to de-accelerate my player:

if (grounded)
{
		if (!Input.GetButton("Horizontal"))
    	rigidbody.velocity.x = Mathf.SmoothDamp(rigidbody.velocity.x, 0, walkDeaccelerationVelx, walkDeacceleration);
		if (!Input.GetButton("Vertical"))
    	rigidbody.velocity.z = Mathf.SmoothDamp(rigidbody.velocity.z, 0, walkDeaccelerationVelz, walkDeacceleration);
    
}

The problem is velocity.x and y aren’t local velocities. What should I be using instead to modify the rigidbody’s local velocity?

Thanks very much!

Personally, I would use rigidbody.AddRelativeForce() and just put negative numbers in there. That should achieve what you are asking.

For goodness sake …

to add force opposite the current velocity, of course you just do this:

rigidbody.AddForce( -rigidbody.velocity )

for example, probably something like

rigidbody.AddForce(-rigidbody.velocity*Time.deltaTime);

or just add drag

rigidbody.drag = 10f

note that of course drag goes along the direction of velocity. what else could it do?

If for some reason you want to add forces in the local coords, Unity give you AddForce AND they give you AddRelativeForce , the latter is in local position coords.

(NOTE - you may be confusing your local positional frame of reference, with, your local velocity frame of reference - recall there’s no particular reason an object has to be pointing the way it is heading. But you should not even have to deal with any of that, it is irrelevant here.)


Note that if, for some incredible reason, you want to calculate “local” velocity. What you’re trying to do is Transform a direction from world space to local space.

You need only use google for “Unity3d Transform a direction from world space to local space”, the first result is the Unity command for “Transforms a direction from world space to local space”.

But again, this won’t help you and is not relevant.

Well, as some people here have said, you can either modify the velocity of a rigid body directly, or you can do it using AddForce/AddRelativeForce. Ultimately they are both exactly the same thing.

The AddForce functions are simply functions that allow you to add to the velocity of a rigid body with a bit of extra maths. For example, the basic ‘AddForce’ version adds a force (in newtons) which adds a number to the velocity that takes into account both the rigid body’s mass and the time step. Ultimately though its still just adding a number!

Onto your question, I think what you’re really asking is ‘how do I break down the rigid body velocity into the bit that points in the same direction as the player, and the bit that points to the players side’. (and in theory the bit that points up too?

We can break down the rigid body’s velocity into 3 values, mess with them, and then add them back up in this fairly long winded bit of code:

//get the velocity
Vector3 myVelocity = rigidBody.velocity;

//get the 3 floats that represent how the rigid body is moving relative to our own transform
float velocityForwards = Vector3.Dot(myVelocity,transform.forwards);
float velocitySideways = Vector3.Dot(myVelocity,transform.right);
float velocityUp = Vector3.Dot(myVelocity,transform.up);

//we could now fiddle with them
velocityForwards *= 0.5f;	//half our forwards velocity
velocitySideways = 0;		//totally kill our sideways velocity!

//and add them back up to get a new velocity
rigidBody.velocity = velocityForwards * transform.forwards + velocitySideways * transform.right + velocityUp * transform.up;

But fortunately Unity provides some functions to make that a bit easier:

//get the velocity
Vector3 myVelocity = rigidBody.velocity;

//convert it to 'local space', so the x is 'how much along our right', etc
myVelocity = transform.InverseTransformDirection(myVelocity);

//we could now fiddle with the individual components
myVelocity.z *= 0.5f;	//half our forwards velocity
myVelocity.x = 0;		//totally kill our sideways velocity!

//and convert back into 'world space'
rigidBody.velocity = transform.TransformDirection(myVelocity);

Personally I don’t think there’s any massive gain to messing with force functions here, as you genuinely do just want to mess with the player’s velocity. But if you did we could still do something like:

//get the velocity
Vector3 myVelocity = rigidBody.velocity;

//convert it to 'local space', so the x is 'how much along our right', etc
myVelocity = transform.InverseTransformDirection(myVelocity);

//we could now fiddle with the individual components
Vector3 amountToAccelerate = Vector3.zero;
amountToAccelerate.z = -myVelocity.z*0.1f; //we are going to reduce our current velocity by 10% along our forwards

//and apply it to the rigid body (we don't need to convert back to world space, as AddRelativeForce does that internally)
rigidBody.AddRelativeForce(amountToAccelerate,ForceMode.Acceleration);

-Chris