Skip to content

Instantly share code, notes, and snippets.

@brihernandez
Last active September 30, 2026 20:30
Show Gist options
  • Select an option

  • Save brihernandez/2bc4d5677903d306579b68faa31e4f00 to your computer and use it in GitHub Desktop.

Select an option

Save brihernandez/2bc4d5677903d306579b68faa31e4f00 to your computer and use it in GitHub Desktop.
This can be used to handle fake aerodynamic forces for an arcade fighter jet, to help it feel like it has some aerodynamics. Actually turning the plane from player input is outside the scope of this gist.
public static class FakeAeroForces
{
/// <summary>
/// Simulates a plane being stalled, which in most planes will result in the nose falling.
/// </summary>
/// <param name="strength">How much the nose is being pulled down. This is a dimensionless
/// number, but in actual usage, this should be N if <see cref="ForceMode.Force"/>, or pure
/// radians/second when using <see cref="ForceMode.Acceleration"/>.</param>
/// <returns>Vector to be used with <see cref="Rigidbody.AddTorque(float, float, float)"/></returns>
public static Vector3 CalculateStallForce(Transform transform, float strength)
{
var pullDownVec = Vector3.Cross(Vector3.up, transform.forward);
return pullDownVec * strength;
}
/// <summary>
/// When a plane banks, the nose will typically slowly fall as the balance of forces was
/// trimmed for level flight, requiring aft stick to compensate. This function simulates the
/// nose down force, and can be used to create a more convincing plane without using physically
/// simulated wings and control surfaces.
/// </summary>
/// <param name="strength">How much the nose is being pulled down. This is a dimensionless
/// number, but in actual usage, this should be N if <see cref="ForceMode.Force"/>, or pure
/// radians/second when using <see cref="ForceMode.Acceleration"/>.</param>
/// <param name="aeroPower">A modifier for the final output. E.g. if your plane turns faster or
/// slower depending on the speed, this normalized value will control the final result.</param>
/// <returns>Vector to be used with <see cref="Rigidbody.AddTorque(float, float, float)"/></returns>
public static Vector3 CalculateAeroNosedownForce(Transform transform, float strength = 1.0f, float aeroPower = 1.0f)
{
var nosePulldown = Mathf.InverseLerp(1, -1, transform.up.y);
var pullDownVec = Vector3.Cross(Vector3.up, transform.forward);
return pullDownVec * (nosePulldown * strength * aeroPower);
}
/// <summary>
/// When a plane banks, the nose of the plane will be pulled slightly in the heading of the
/// bank. This allows a plane to turn with slight bank, and a tiny bit of nose up to compensate.
/// The resultant forces from this function are a bit weird, and are meant to be combined with
/// <see cref="CalculateAeroNosedownForce(Transform, float, float)"/> to create a convincing
/// effect.
/// </summary>
/// <param name="strength">How much the nose is being turned. This is a dimensionless number,
/// but in actual usage, this should be N if <see cref="ForceMode.Force"/>, or pure
/// radians/second when using <see cref="ForceMode.Acceleration"/>.</param>
/// <param name="aeroPower">A modifier for the final output. E.g. if your plane turns faster or
/// slower depending on the speed, this normalized value will control the final result.</param>
/// <returns>Vector to be used with <see cref="Rigidbody.AddTorque(float, float, float)"/></returns>
public static Vector3 CalculateAeroBankForce(Transform transform, float strength = 0.5f, float aeroPower = 1.0f)
{
var bank = transform.right.y;
var bankVec = Vector3.up;
return bankVec * (bank * -strength * aeroPower);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment