- Home /
Get velocity of point offset from center of rigidbody
I have a cube with a rigidbody, and I can get the velocity of the entire cube with cube.GetComponent<Rigidbody>().velocity
. But is it possible to get the velocity of a point on the cube offset from the center, say cube.transform.TransformPoint(0, 0, 1)
? For example, a cube spinning in place would have a velocity of zero, but at the given point it might have a velocity perpendicular to the spin direction. Is there a built in method in Unity to do this, or do I have to program it in myself?
I don't think there is but if you can find that point any time you can save the position and next frame get the position - last position. This of course means you get the result one frame later.
Answer by Bunny83 · May 26, 2016 at 07:42 PM
edit
Actually my initial answer was wrong. Unity actually has a method that does calculate this (Thanks to @Habitablaba).
It's called "GetPointVelocity". You just have to pass a world space point and it returns the current velocity of that point. If you have a local point you first need to transform it into worldspace by using transform.TransformPoint().
The following is my original answer where i (re)invented that method myself ^^.
No, there's no built-in function to return the temporary linear velocity of a given point.
Of course that velocity would change each frame.
If you want to calculate it yourself you should keep in mind that physics are calculated in worldspace. To convert the angularVelocity into a linear velocity you have to calculate the distance of your point from the centerOfMass not from the object's origin because that's the point around the RB will rotate. Once you have calculated the tangential velocity you just need to add the linear velocity of the RB to get the final velocity for this moment.
There are basically two different ways how you could convert the angular velocity into a linear velocity:
either calculate the real tangential velocity so it will be perpendicular to the distance vector and the rotation axis
or calculate the next point where the point will be, following the actual rotation and draw a line between the current position and the next one. Of course this line will be slightly shorter as it's a chord of the orbit circle.
ps: the centerOfMass is given in local coordinates. It's the easiest way to calculate the distance vector in local space (P - centerOfMass) so you get a local space direction vector. Then just use transform.TransformDirection to get the worldspace direction.
edit
I quickly wrote this extension method:
public static class RigidbodyExtension
{
public static Vector3 GetLinearVelocityAtPoint(this Rigidbody aRigidbody, Vector3 aLocalPoint)
{
var p = aLocalPoint - aRigidbody.centerOfMass;
var v = Vector3.Cross(aRigidbody.angularVelocity, p);
v = aRigidbody.transform.TransformDirection(v);
v += aRigidbody.velocity;
return v;
}
}
This should return what you want. You can simply use it like this:
Rigidbody rb;
Vector3 localPoint;
Vector3 velAtPoint = rb.GetLinearVelocityAtPoint(localPoint);
Haven't verified everything is correct but first tests seems to be ok. The angular velocity is in radians per second and the resulting velocity is in units per second.
I would also point out rigidbody.GetPointVelocity and rigidbody.GetRelavitePointVelocity
Ohh, never seen those two methods ^^. For how long do they exist? Now i have to compare the output with my approach ^^. Thanks for the hint.
edit
:D Yes GetPointVelocity does exactly the same as my extension but it takes a world space point ins$$anonymous$$d of a local point.
GetRelavitePointVelocity seems to take a local point and returns a local velocity vector.
I'll edit my answer ...
Strange, i just checked the oldest version of Unity i could find on my PC which was Unity3.0 and there GetPointVelocity already existed ^^. I have no idea how i missed those all the time :)