I want to make a simple aircraft controller, what looks like little realistic in unity. I watch some video from airplane physics. and make a simple script in unity, but if I start, my plane cant move or if I change drag to zero, it cant lift. I tried to use real data and get it from wiki(F22 Raptor). To my game object, I gave the rigidbody component mass = 19670 kg. Engine thrust = 2 * 116000.0f Newton.
private void calculateEnginePower()
{
EnginePower = engineThrust * ThrottleInput;
}
private void calculateForces()
{
angleOfAttack = Vector3.Angle(Vector3.forward, rb.velocity);
angleOfAttack = Mathf.Clamp(angleOfAttack, 0, 90);
coefficient = Mathf.Pow(1225.04f * rb.velocity.magnitude, 2) - 1; //M^2-2 where: M is mach.
if (coefficient > 0.0f)
coefficientLift = (4 * angleOfAttack) / Mathf.Sqrt(coefficient);
lift = 1.2754f * 0.5f * Mathf.Pow(rb.velocity.magnitude, 2) * coefficientLift * 78.04f; // densy1.2754 kg/m3, speed m/s , (F22)Wing area: 840 ft² (78.04 m²)
coefficientDrag = 0.021f;
rb.drag = coefficientDrag * 0.5f * Mathf.Pow(rb.velocity.magnitude,2) * 1.2754f * 78.04f;
rb.AddForce(transform.up * lift);
rb.AddForce(transform.forward * EnginePower);
}
used these formulas:
for Lift force: Lift formula for Lift coefficient: Cl formula for Drag: Drag formula and for Drag coefficient: I used data from wiki too (0.021f).
A plane is an infinitely large, flat surface that exists in 3D space and divides the space into two halves known as half-spaces. It is easy to determine which of the two half-spaces a particular point is in and also how far the point is from the plane.
The four forces are lift, thrust, drag, and weight. As a Frisbee flies through the air, lift holds it up. You gave the Frisbee thrust with your arm. Drag from the air made the Frisbee slow down.
aerodynamics, branch of physics that deals with the motion of air and other gaseous fluids and with the forces acting on bodies passing through such a fluid. Aerodynamics seeks, in particular, to explain the principles governing the flight of aircraft, rockets, and missiles.
So there are a number of issues with your code. I've outlined them below;
Calculate Forces
Issue:
angleOfAttack = Vector3.Angle(Vector3.forward, rb.velocity);
Vector3.forward
and rb.velocity
are both in world-space. AoA
is the angle between the local chord-line of your wing and the aircraft's velocity
. Vector3.Angle
will return an unsigned angle. AoA
must work in both positive and negative directions otherwise negative pitch and inverted flight would not be possible.Solution: Move
rb.velocity
to local-space and solve forAoA
with trigonometry.
// *flip sign(s) if necessary*
var localVelocity = transform.InverseTransformDirection(rb.velocity);
var angleOfAttack = Mathf.Atan2(-localVelocity.y, localVelocity.z);
Issue:
coefficient = Mathf.Pow(1225.04f * rb.velocity.magnitude, 2) - 1;
4α/sqrt(M^2−1)
is a supersonic wave coefficient for M > 1. At zero velocity this equation will reduce to sqrt(-1)
which is an imaginary number that will produce NaN
. Mach is expressed as M=V/C
where V=velocity
and C=the speed of sound
. Your 1225.04f
constant must be C
in units of km/h and not m/s as required. You're also multiplying and not dividing as given in the equation.Solution: Simplify your equations with Lifting Line Theory.
var aspectRatio = (wingSpan * wingSpan) / wingArea;
var inducedLift = angleOfAttack * (aspectRatio / (aspectRatio + 2f)) * 2f * Mathf.PI;
var inducedDrag = (inducedLift * inducedLift) / (aspectRatio * Mathf.PI);
Source: Aerospaceweb.org
Issue:
rb.drag = coefficientDrag * 0.5f * Pow(rb.velocity.mag,2) * 1.2754f * 78.04f;
rb.drag
is not required since we're calculating and applying drag manually.Solution: Set the
rb.drag
property to the smallest possible value.
rb.drag = Mathf.Epsilon; // set in Awake
Issue:
rb.AddForce(transform.up * lift);
transform.up
is not correct for lift
. Lift acts perpendicular to velocity
while drag
acts parallel.Solution: Compute the
lift
direction by crossing the normalizedvelocity
vector with the aircraft's lateral direction and applydrag
opposite tovelocity
.
// *flip sign(s) if necessary*
var dragDirection = -rb.velocity.normalized;
var liftDirection = Vector3.Cross(dragDirection, transform.right);
rb.AddForce(liftDirection * lift + dragDirection * drag);
Your lift equation looks OK, so putting it all together would look something like this; (Untested)
public float wingSpan = 13.56f;
public float wingArea = 78.04f;
private float aspectRatio;
private void Awake ()
{
rb.drag = Mathf.Epsilon;
aspectRatio = (wingSpan * wingSpan) / wingArea;
}
private void calculateForces ()
{
// *flip sign(s) if necessary*
var localVelocity = transform.InverseTransformDirection(rb.velocity);
var angleOfAttack = Mathf.Atan2(-localVelocity.y, localVelocity.z);
// α * 2 * PI * (AR / AR + 2)
var inducedLift = angleOfAttack * (aspectRatio / (aspectRatio + 2f)) * 2f * Mathf.PI;
// CL ^ 2 / (AR * PI)
var inducedDrag = (inducedLift * inducedLift) / (aspectRatio * Mathf.PI);
// V ^ 2 * R * 0.5 * A
var pressure = rb.velocity.sqrMagnitude * 1.2754f * 0.5f * wingArea;
var lift = inducedLift * pressure;
var drag = (0.021f + inducedDrag) * pressure;
// *flip sign(s) if necessary*
var dragDirection = rb.velocity.normalized;
var liftDirection = Vector3.Cross(dragDirection, transform.right);
// Lift + Drag = Total Force
rb.AddForce(liftDirection * lift - dragDirection * drag);
rb.AddForce(transform.forward * EnginePower);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With