- Home /
Set Velocity at relative position.
I basically want to use
Rigidbody.AddForceAtPosition
But instead set the velocity of a Rigidbody at a given position.
I thought I could use the following code: This line to first cancel the current velocity at Point
Body.AddForceAtPosition(-Body.GetRelativePointVelocity(Point), Body.transform.TransformPoint(Point), ForceMode.VelocityChange);
And this line to add the new velocity.
Body.AddForceAtPosition(newVelocity, Body.transform.TransformPoint(Point), ForceMode.VelocityChange);
This seemed simple enough but the first line is causing the Rigidbody to freak out, switching quickly between two positions every frame. This happens no matter the orientation of the object or the position of Point.
Answer by Bunny83 · Dec 06, 2017 at 02:19 PM
No there's no way to set the velocity of a given point. It also wouldn't make any sense. The velocity at a given point is calculated on the fly and is the combination of linear and angular velocity. Applying an appropriate counter force at a point does stop the point temporarily. However the exact force needed depends on three factors:
linear velocity
angular velocity
inertia tensor (+rotation)
( and of course the point )
That's what the physics system has to take into account when applying collision forces. However velocity change for a single point makes not much sense.
Imagine you have a floating rigidbody that has no velocity / angular velocity. Say you want the local point (1,0,0) to get a velocity of (0,0,1). You could just add a linear velocity of (0,0,1) to the rigidbody and you get your desired velocity. However instead you could also apply only an angular velocity of (0,-1,0) and also get a velocity of (0,0,1) without having the rigidbody move at all. Of course in case of angular velocity the point velocity will change as the object rotates since the point velocity is the tangential velocity around the center of mass. Of course it's also possible to add both, linear and angular velocity in any combination. There simply isn't a general way how setting the velocity of a point should affect the velocity / angular velocity of a Rigidbody.
What Unity does when you use "AddForceAtPosition" is to do both, adding a linear velocity and a angular velocity. However it does not split the added force / impulse / velocity. It simply adds the velocity change directly to the linear velocity. In addition, depending on where the force is applied it adds angular velocity as well. Though the further out the point is from the center of mass, the more angular velocity is added. This generally makes sense, however Unity does not really preserve energy / momentum. It should split the applied momentum between linear and angular velocity which it doesn't do.
GetRelativePointVelocity
Just another note on this method: It doesn't work as it's implemented wrong, so don't use it.
They made a mistake when implementing this method. While GetPointVelocity works as expected, they messed up local and world space velocities in GetRelativePointVelocity. Here's a reference implementation of GetPointVelocity:
public static Vector3 GetVelocityAtPoint(this Rigidbody aRB, Vector3 aPoint)
{
var linVel = aRB.velocity;
var angVel = aRB.angularVelocity;
var d = aPoint - aRB.worldCenterOfMass;
return Vector3.Cross(angVel, d) + linVel;
}
This method does return the same value as "GetPointVelocity". That is the current worldspace velocity of the given point. However "GetRelativePointVelocity" seems to calculate the tangential velocity in localspace but in the end they add the local space tangential velocity to the world space linear velocity which makes no sense. Their method usually returns a constant value which is impossible for a rotating and moving rigidbody. It's not clear if they intended to return a local space velocity (in which case they have to convert the linear velocity into localspace) or if they wanted to return a worldspace velocity (in which case they need the tangential velocity in world space).
This would be the correct way to pass in a local vector and return a worldspace velocity vector:
public static Vector3 GetRelativePointVelocity2(this Rigidbody aRB, Vector3 aLocalPoint)
{
var linVel = aRB.velocity;
var angVel = aRB.angularVelocity;
var d = aRB.transform.TransformPoint(aLocalPoint) - aRB.worldCenterOfMass;
return Vector3.Cross(angVel, d) + linVel;
}
Unity's physics system is just a rough approximation of real world physics. For example in Unity an object does not keep it's proper angular momentum. So a tumbling motion like explained in this video is impossible in Unity as Unity will keep the angular velocity constant with no external force / torque applied.
Answer by Ginxx009 · Dec 06, 2017 at 03:51 AM
There is no AddRelativeForceAtPosition, but you can translate the local position you have into world space before applying the force:
Why do you try something like this:
Vector3 worldForcePosition = transform.TransformPoint(yourLocalForcePosition);
rigidbody.AddForceAtPosition(force, worldForcePosition);
That's not really what i'm after. I already do all needed transforms, I don't see the problem with my code, that's my problem. Adding the negative of the current velocity should cancel the velocity. But I get weird bouncing and the rigidBody freaks out if I move it
try this on your start(); rigidbody.freezeRotation = true;
and change the script to use forces or set rigidbody.velocity; to reduce bouncing, increase rigidbody.drag - this also limits the max speed.
The thing is, I have already got this working perfectly If I set the velocity of the object. But that only works for the overall velocity. I want to set the velocity at a certain position of the rigidBody. So I use AddForceAtPosition to add the inverse of the current point velocity. This should cancel the point velocity. I don't know why it doesn't work as expected
Your answer
Follow this Question
Related Questions
object move towards to mouse position 0 Answers
How to apply in opposite direction to transform? 1 Answer
Get result (force & torque) of AddForceAtPosition? 2 Answers
Rigidody.velocity = Direction * speed; How to get direction? 1 Answer
How to get my child objects to follow the parent? Also, not sure if this is working. 0 Answers