Class Airfoil
Represents a finite wing that simulates aerodynamic forces using section-based calculations. Supports 1500+ airfoil profiles, automatic mesh fitting, control surface integration, and mirroring for symmetric aircraft. The airfoil is divided into spanwise sections, with each section calculating local lift, drag, and moment forces.
Namespace: NWH.Aerodynamics.Airfoils
Assembly: NWH.Aerodynamics.dll
Syntax
[Serializable]
public class Airfoil : MonoBehaviour
Remarks
The airfoil uses a finite plane geometry defined by four corner points and divides it into multiple sections along the span. Each section independently calculates aerodynamic forces based on local flow conditions. Control surfaces (ailerons, rudders, etc.) are treated as separate airfoils attached to the main airfoil.
Fields
| Edit this page View SourceaTransform
Custom simplified Transform implementation used for positioning the Airfoil.
Declaration
[Tooltip("Custom simplified Transform implementation used for positioning the Airfoil.")]
public AirfoilTransform aTransform
Field Value
| Type | Description |
|---|---|
| AirfoilTransform |
aerodynamicCenterChordPosition
Position of the aerodynamic center along the chord line where lift force is applied. Value of 0 is the leading edge (front), 1 is the trailing edge (rear). Typically 0.25 (25% chord) for most airfoils.
Declaration
[Range(0, 1)]
[Tooltip("Position of the aerodynamic center along the chord line.")]
public float aerodynamicCenterChordPosition
Field Value
| Type | Description |
|---|---|
| float |
airfoilProfile
AirfoilProfile asset containing the lift, drag, and moment curves for this airfoil. Defines aerodynamic characteristics based on angle of attack.
Declaration
[Tooltip("AirfoilProfile that determines the performance of this airfoil.")]
public AirfoilProfile airfoilProfile
Field Value
| Type | Description |
|---|---|
| AirfoilProfile |
controlAngle
Deflection angle in degrees from the neutral position. Only applies if this is a control surface. Positive values typically deflect downward/right, negative values deflect upward/left depending on orientation.
Declaration
[Tooltip("Deflection angle from the original position if the Airfoil is a control surface.")]
public float controlAngle
Field Value
| Type | Description |
|---|---|
| float |
controlSurfaceAirfoils
Airfoils attached to this airfoil that represent control surfaces, such as ailerons, rudders, ailerators, etc.
Declaration
[Tooltip(" Airfoils attached to this airfoil that represent control surfaces, such\r\n as ailerons, rudders, ailerators, etc.")]
public List<Airfoil> controlSurfaceAirfoils
Field Value
| Type | Description |
|---|---|
| List<Airfoil> |
dragCenterChordPosition
Position along the chord line where drag force is applied. Value of 0 is the leading edge, 1 is the trailing edge. Typically 0.25-0.5 for most airfoils.
Declaration
[Range(0, 1)]
[Tooltip("Position of the aerodynamic center along the chord line.")]
public float dragCenterChordPosition
Field Value
| Type | Description |
|---|---|
| float |
dragCoefficient
Overall multiplier for drag force. Scales the drag calculated from the airfoil profile curves. Values below 1.0 reduce drag, above 1.0 increase drag. Default 1.0.
Declaration
[Tooltip("Coefficient of drag generated by airfoil.")]
public float dragCoefficient
Field Value
| Type | Description |
|---|---|
| float |
fPlane
Defines the planform shape of the airfoil using four corner points (a, b, c, d). Used to calculate wing area, span, chord length, and section geometry.
Declaration
[Tooltip("FinitePlane that determines the dimensions of the airfoil.")]
public FinitePlane fPlane
Field Value
| Type | Description |
|---|---|
| FinitePlane |
isControlSurface
True if the airfoil is a control surface (rudder, elevator, etc.). Should only be true if the Airfoil is attached to another Airfoil.
Declaration
[Tooltip(" True if the airfoil is a control surface (rudder, elevator, etc.).\r\n Should only be true if the Airfoil is attached to another Airfoil.")]
public bool isControlSurface
Field Value
| Type | Description |
|---|---|
| bool |
liftCoefficient
Overall multiplier for lift force. Scales the lift calculated from the airfoil profile curves. Values below 1.0 reduce lift, above 1.0 increase lift. Default 1.0.
Declaration
[Tooltip("Coefficient of lift generated by airfoil.")]
public float liftCoefficient
Field Value
| Type | Description |
|---|---|
| float |
mirrorControlAirfoils
Should control airfoils be mirrored to the mirroring target?
Declaration
[Tooltip("Should control airfoils be mirrored to the mirroring target?")]
public bool mirrorControlAirfoils
Field Value
| Type | Description |
|---|---|
| bool |
mirrorSlicingPoints
Should slicing points be mirrored to the mirroring target?
Declaration
[Tooltip("Should slicing points be mirrored to the mirroring target?")]
public bool mirrorSlicingPoints
Field Value
| Type | Description |
|---|---|
| bool |
mirroringTarget
GameObject to which the Airfoil will be mirrored. Optional.
Declaration
[Tooltip("GameObject to which the Airfoil will be mirrored. Optional.")]
public GameObject mirroringTarget
Field Value
| Type | Description |
|---|---|
| GameObject |
momentCoefficient
Overall multiplier for pitching moment. Scales the moment calculated from the airfoil profile curves. Values below 1.0 reduce moment, above 1.0 increase moment. Default 0.0 (disabled).
Declaration
[Tooltip("Coefficient of moment/torque generated by airfoil.")]
public float momentCoefficient
Field Value
| Type | Description |
|---|---|
| float |
sections
Sections/slices of the airfoil. Airfoil is sliced into smaller sections/slices and each section is then simulated individually.
Declaration
[Tooltip(" Sections/slices of the airfoil.\r\n Airfoil is sliced into smaller sections/slices and each section is then simulated individually.")]
public List<AirfoilSection> sections
Field Value
| Type | Description |
|---|---|
| List<AirfoilSection> |
sliceCount
Number of spanwise divisions for the airfoil. Results in sliceCount+1 AirfoilSections. Typical range 4-10. Higher values improve accuracy at the cost of performance.
Declaration
[Tooltip(" Number of slices along the airfoil. Will result in sliceCount+1 AirfoilSections.\r\n Using higher number will produce somewhat higher quality simulation but will\r\n impact performance in linear fashion.")]
public int sliceCount
Field Value
| Type | Description |
|---|---|
| int |
Remarks
Each additional slice adds one more physics calculation per frame. 4 slices = 5 sections, suitable for small wings. 10 slices = 11 sections, suitable for large wings or wings with significant spanwise variation.
slicingPoints
Local X-axis positions where the airfoil is divided into sections. Always sorted from smallest to largest. Automatically generated by GenerateSlicingPoints() based on sliceCount.
Declaration
[Tooltip("Slicing points along the local X axis, always in order from smaller to larger value.")]
public List<float> slicingPoints
Field Value
| Type | Description |
|---|---|
| List<float> |
targetRigidbody
Rigidbody to which the forces are applied.
Declaration
[Tooltip("Rigidbody to which the forces are applied.")]
public Rigidbody targetRigidbody
Field Value
| Type | Description |
|---|---|
| Rigidbody |
Methods
| Edit this page View SourceAutoSetup()
Automatically configures the airfoil by analyzing the mesh geometry and creating optimal section divisions.
Declaration
public void AutoSetup()
Remarks
Performs the following steps in order:
- Resets geometry to defaults
- Orientates the airfoil plane to match the mesh surface
- Fits the finite plane corners to the mesh bounds
- Generates slicing points based on sliceCount
- Creates airfoil sections from the slicing points
FindControlSurfaces()
Declaration
public void FindControlSurfaces()
FitToMesh()
Adjusts the finite plane corner points to match the mesh bounding area in the airfoil's local space.
Declaration
public void FitToMesh()
Remarks
Finds the four corner vertices of the mesh that correspond to the wing's planform corners. The corners are projected onto the airfoil plane and aligned to ensure parallel leading/trailing edges. This creates an accurate representation of the wing's planform shape for force calculations. Requires a MeshFilter component on the parent GameObject.
Flip()
Declaration
public void Flip()
GenerateSlicingPoints()
Generates spanwise positions where the airfoil will be divided into sections.
Declaration
public void GenerateSlicingPoints()
Remarks
Creates evenly-spaced slicing points along the local X-axis between the wing root and tip. The number of points is determined by sliceCount, resulting in sliceCount+1 sections. Points are automatically sorted and aligned with the finite plane geometry.
LinePlaneIntersection(Vector3, Vector3, Vector3, Vector3)
Declaration
public static Vector3 LinePlaneIntersection(Vector3 planePoint, Vector3 planeNormal, Vector3 linePoint, Vector3 lineDirection)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | planePoint | |
| Vector3 | planeNormal | |
| Vector3 | linePoint | |
| Vector3 | lineDirection |
Returns
| Type | Description |
|---|---|
| Vector3 |
Mirror(GameObject, float)
Creates or updates a mirrored copy of this airfoil on the target GameObject.
Declaration
public void Mirror(GameObject target = null, float positionThreshold = 0.02)
Parameters
| Type | Name | Description |
|---|---|---|
| GameObject | target | GameObject to receive the mirrored airfoil. If null, automatically searches for a symmetric counterpart. |
| float | positionThreshold | Maximum position difference in meters to consider a GameObject as the mirror target. |
Remarks
Mirrors the finite plane geometry, airfoil profile, and all settings to create a symmetric wing. If mirrorControlAirfoils is enabled, also mirrors all attached control surfaces. Useful for quickly setting up symmetric aircraft without manual duplication.
MirrorSlicingPoints(Airfoil, Airfoil)
Declaration
public static void MirrorSlicingPoints(Airfoil source, Airfoil target)
Parameters
| Type | Name | Description |
|---|---|---|
| Airfoil | source | |
| Airfoil | target |
MirrorSlicingPointsFrom(Airfoil)
Copies and transforms slicing points from a source airfoil to this airfoil's local space.
Declaration
public void MirrorSlicingPointsFrom(Airfoil source)
Parameters
| Type | Name | Description |
|---|---|---|
| Airfoil | source | Source airfoil whose slicing points will be copied. |
Remarks
Used to ensure symmetric wings have matching section divisions. Only includes points that fall within this airfoil's span range. Automatically re-slices the airfoil after copying points.
OnDrawGizmosSelected()
Declaration
public void OnDrawGizmosSelected()
OrientateToMesh()
Aligns the airfoil's local coordinate system to match the best-fitting plane through the mesh vertices.
Declaration
public void OrientateToMesh()
Remarks
Uses principal component analysis to find the plane that best fits the mesh geometry. The airfoil's up vector is aligned to the mesh surface normal, ensuring proper lift direction. Requires a MeshFilter component on the parent GameObject.
ResetGeometry()
Declaration
public void ResetGeometry()
SetDefaults()
Sets airfoil defaults.
Declaration
public void SetDefaults()
Slice()
Divides the airfoil into spanwise sections at the generated slicing points.
Declaration
public void Slice()
Remarks
Creates AirfoilSection objects for each segment of the wing between slicing planes. Each section calculates its own area, chord length, and aerodynamic center. Also matches control surface sections to their corresponding main wing sections for coordinated simulation. Sections with area below 0.002 m² are discarded as too small for meaningful simulation.