Unity aircraft physics
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
andrb.velocity
are both in world-space.AoA
is the angle between the local chord-line of your wing and the aircraft'svelocity
. -
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 tosqrt(-1)
which is an imaginary number that will produceNaN
. Mach is expressed asM=V/C
whereV=velocity
andC=the speed of sound
. Your1225.04f
constant must beC
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 forlift
. Lift acts perpendicular tovelocity
whiledrag
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);
}
Boyesz
Updated on July 07, 2022Comments
-
Boyesz almost 2 years
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).
-
Ian H. about 6 yearsHave you tried debugging to see the values of
lift
andEnginePower
? Where are you callingcalculateForces
? -
Boyesz about 6 yearsroll,pitch... inputs from keyboard and mouse, EnginePower is a simple property and i call the Move function in a controller inside void Update. public void Move(float roll, float pitch, float yaw, float throttle) { // transfer input parameters into properties.s RollInput = roll; PitchInput = pitch; YawInput = yaw; ThrottleInput = throttle; AirBrakes = false; calculateEnginePower(); calculateForces(); calculateRotation(); }
-
Boyesz about 6 yearsyou can call it too in Move function for debugging. private void debugThings() { Debug.Log("Aoa: " + angleOfAttack); Debug.Log("cL: " + coefficientLift); Debug.Log("Lift: " + lift); Debug.Log("cD: " + coefficientDrag); Debug.Log("Drag: " + drag); Debug.Log("Mass: " + rb.mass); Debug.Log("Speed: " + rb.velocity.magnitude); Debug.DrawLine(rb.position, rb.velocity * 300, Color.red); }
-
meowgoesthedog about 6 yearsWhat are typical values for
lift
at full thrust? How do they compare to the weight of the plane? (g
might not be 9.81 in Unity units, but I'm unsure about that - best way is to find out with an experiment). According to this forum thedrag
property seems to have rather arbitrary units (and it is unclear what it exactly represents)
-