# Problem with physics: GetPointVelocity & AddForceAtPosition (airplane control script)

Im trying to make a simple airplane control script. I've seen some advise on the subject on the forums (here) which helped a lot.

In summary:

Make a script that is applied to a GameObject parented to a rigidbody. This script calculates a lift force from its speed and angle and applies it to the parent at its position.

Only that my script uses the velocity of the parent rigidbody instead of its own. That isn't a good solution and limits the use of my script more or less to the main wings of a plane (their velocity is close to the velocity of the plane most of the time).

I believe I have to use GetPointVelocity() to get the speed of the child. When i do that my plane starts to rotate violently around various axes and moves rather slow in some random direction. Im a little lost here. I'm also new to javascript, any help would be appreciated.

Edit:

I have tried some fixes but nothing worked so far.

The updated script is postet below.

I believe the Problem is, that when I calculate a force based on a velocity from GetPointVelocity() and use that Force with AddForceAtPosition() on the same rigidbody, some sort of feedback messes things up. Is that possible?

Here is my script:

``````/*
This script simulates a simple Wing.
*/

var sizeX = 7.0; //dimensions of Wing
var sizeZ = 1.2;

var maxAngleOfAttack = 0.7; //above this Angle no Lift will be generatet because of stall
var maxForce = 1000;

private var debug_vec1 = Vector3.zero;
private var debug_vec2 = Vector3.zero;

private var liftVec = Vector3.zero;

function OnDrawGizmos () {
Gizmos.color = Color (0.20, 0.74, 0.27, 0.50);
var leftEdge = transform.right * (-sizeX/2);
var rightEdge =transform.right * (sizeX/2);
var leadingEdge = transform.forward * (sizeZ/2);
var trailingEdge = transform.forward * (-sizeZ/2);

var ourPosition = transform.position;

Gizmos.DrawLine (ourPosition+rightEdge+trailingEdge, ourPosition+leftEdge+trailingEdge);

Gizmos.color = Color (0.28, 0.32, 0.97, 0.50);
Gizmos.DrawLine (ourPosition, ourPosition+debug_vec1);
Gizmos.color = Color (0.80, 0.17, 0.17, 0.50);
Gizmos.DrawLine (ourPosition, ourPosition+debug_vec2);
}

function FixedUpdate () {

//Get velocity at our location (brroken use root velocity instead)
var v : Vector3;
//v = transform.root.rigidbody.GetPointVelocity(transform.position);
v = transform.root.rigidbody.velocity;
//only y and z contribute to lift
v -= Vector3.Project(v, transform.right);
debug_vec1 = v;

//forward speed
var airspeed = v.magnitude;

//angle of attack (-1 = moving up; 1 = m. down; 0 = m. forward or backward)
var attacKAngle = Vector3.Dot(v.normalized, transform.up.normalized * -1);
if (attacKAngle >  maxAngleOfAttack || attacKAngle < -maxAngleOfAttack)  attacKAngle = 0;

//liftforce
//area of the wing * density of air / 2 (used as Multiplier to liftforce)
var liftMult = sizeX * sizeZ * 0.645;

var liftForce = airspeed * liftMult * attacKAngle;
if (liftForce > maxForce) liftForce = maxForce;
if (liftForce < -maxForce) liftForce = -maxForce;

//Apply Lift Force to Parent rigidbody at our Position
debug_vec2 = liftForce*transform.up;

}

``````

I don't think there is any feedback effect here - this is a common technique for implementing car physics, for example.

It is often difficult to keep things consistent between local and world coordinates spaces. Since most forces affecting a vehicle are best expressed in local coordinates, it helps to convert all velocities, forces etc into local space first, do all the calculations and then convert back. You can use transform.InverseTransformDirection to go from world to local space and then transform.TransformDirection to go back to world space.

For example, get the point velocity for a wing using GetPointVelocity and then convert it to local coordinates:-

``````var worldWingVel: Vector3 = rigidbody.GetPointVelocity(wingPoint);
var localWingVel: Vector3 = transform.InverseTransformDirection(worldWingVel);

``````

You can then remove the sideways component of the wing velocity using

``````localWingVel.x = 0;

``````

...and get the lift using

``````var localLift: Vector3 = liftValue * Vector3.up;

``````

Eventually, you need to convert this back to world space, because AddForceAtPosition doesn't have a local space equivalent:-

``````var worldLift: Vector3 = transform.TransformDirection(localLift);