AircraftController

Purpose and Role
The AircraftController is the primary component of the NWH Aerodynamics asset and the main hub for aircraft physics simulation in the aerodynamics system. It binds together all aircraft-related components such as propulsion, lights, effects, instruments, sound systems, and environmental interactions.
As the central controller, it manages all aircraft-related subsystems including aerodynamic forces, flight dynamics, engines, control surfaces, landing gear, fuel system, and flight instruments. While the AircraftController provides the core framework and flight data calculations, the actual aircraft flight behavior emerges from the modular, component-based architecture where aircraft systems are independent yet integrated.
This component extends the Vehicle base class and requires a Rigidbody, VariableCenterOfMass component, and AircraftInputManager to function. It provides a unified interface for querying aircraft state and integrating custom systems. The aircraft also requires input providers to be present in the scene (separate from the per-aircraft input manager - input providers are scene-level and can serve multiple aircraft).
Component-Based Architecture
The NWH Aerodynamics system uses a modular, component-based architecture rather than a monolithic approach. The AircraftController serves as the central hub that binds together independent, reusable components that each handle specific aspects of aircraft behavior.
Design Philosophy
Decoupled Subsystems: Each aircraft subsystem (engines, control surfaces, fuel system, instruments, audio, etc.) is implemented as a separate component that can be:
- Added or removed independently
- Configured separately without affecting other systems
- Reused across different aircraft
- Extended with custom functionality
Component Interaction: Components interact through:
- The AircraftController as a central reference point
- Shared Rigidbody for physics
- Public event systems (OnCollision, etc.)
- Direct property access through the AircraftController
Modular Aircraft Design: An aircraft is composed by adding the components it needs:
- A simple glider has: AircraftController + Rigidbody + VariableCenterOfMass + AircraftInputManager + Airfoils
- A powered aircraft adds: Engines + Propulsors + Fuel System
- A complex aircraft adds: Landing Gear + Sound Systems + Instruments + Effects + Advanced Controls
- Scene must have: Input Providers (InputManagerSceneInputProvider, InputSystemSceneInputProvider, etc.)
This approach provides flexibility and allows creating aircraft of varying complexity without unnecessary overhead. Note that input providers are scene-level and shared among all vehicles, while each aircraft has its own AircraftInputManager.
Architecture Overview
The AircraftController manages several key subsystems:
Core Aerodynamics
- Airfoil sections - Generate lift and drag based on airspeed and angle of attack
- Control surfaces - Ailerons, elevators, rudders modify aerodynamic forces for flight control
- Drag objects - Handle non-lift producing drag (fuselage, landing gear)
- Wind effects - Accounts for environmental wind affecting relative airflow
Aircraft Systems
- Engines - Piston or turbine engines with propeller/jet propulsion
- Landing gear - Ground contact detection and retraction/extension
- Fuel system - Multiple tanks with consumption modeling
- Instruments - Real-time flight data display (airspeed, altitude, attitude, heading)
- Sound management - Aircraft audio including engines, wind, and crash effects
- Effects - Lights, smoke systems, exhaust visualization
Physics Integration
- Center of mass - Automatically adjusts with fuel consumption and payload changes
- Flight data - Calculates airspeed, angle of attack, pitch/roll/yaw, altitude, heading
- Velocity tracking - Accounts for both aircraft motion and environmental factors
Setup Requirements
Per-Aircraft Components
The AircraftController automatically requires:
- Rigidbody - Physics body with appropriate mass and inertia tensor for realistic flight
- VariableCenterOfMass - Manages dynamic center of mass adjustments
- AircraftInputManager - Per-aircraft input manager that receives input from providers and distributes to control surfaces
- One per aircraft (automatically added with AircraftController)
- Retrieves input from scene-level input providers
- Stores input states (throttle, ailerons, elevator, rudder, etc.)
- Can be manually controlled or auto-fed from input providers
Scene-Level Components (Shared)
The scene must contain input providers to supply input data:
- Input Providers - Scene-level classes that capture raw input (one or more per scene)
- Examples:
InputManagerSceneInputProvider,InputSystemSceneInputProvider,MobileSceneInputProvider - Capture keyboard, gamepad, mouse, or touch input
- Multiple providers can coexist (primary vs secondary input methods)
- All aircraft/vehicles in the scene read from available providers
- Implement
AircraftInputProviderBasefor aircraft-specific input mapping
- Examples:
Rigidbody Configuration
Proper Rigidbody setup is critical for realistic flight behavior:
- Mass - Should reflect aircraft weight (typical: 500-5000 kg for general aviation)
- Drag - Leave at default or 0; aerodynamics handle drag calculation
- Angular Drag - Typically 0.05-0.1 for realistic rotational behavior
- Constraints - Uncheck "Freeze Rotation" to allow full 6-DOF motion
Inertia Tensor
The aircraft's inertia tensor controls rotational dynamics and stall behavior:
- Pitch inertia (X) - Controls pitch sensitivity; higher values = slower pitch response
- Roll inertia (Z) - Controls roll sensitivity; higher values = slower roll response
- Yaw inertia (Y) - Controls yaw sensitivity; higher values = slower yaw response
Use the Aircraft Setup Wizard for automated configuration of common aircraft types, or manually adjust based on the aircraft's physical dimensions and mass distribution.
Inspector Interface
The AircraftController inspector provides three main tabs for configuration and interaction:
Components Tab
The Components Tab displays a list of buttons with options to add different aircraft-related MonoBehaviours to the aircraft. Once a component is added, the button is greyed out, indicating the component is already present. All required components are added by default when the AircraftController is created.
Available component options include:
- Propulsion - Engine and propulsor systems
- Control Surfaces - Ailerons, elevators, rudders, flaps
- Landing Gear - Wheel assemblies with ground detection
- Fuel System - Fuel tanks and consumption management
- Environmental Systems - Atmosphere, wind, and weather interaction
- Effects - Lights, smoke, exhaust visualization
- Sound Systems - Engine, wind, and crash audio
- Instruments - Flight instruments (airspeed, altitude, attitude, etc.)
- Input System - Control input manager
This tab provides a convenient interface for adding missing subsystems without manually instantiating MonoBehaviours.
About Tab
The About Tab provides a collection of useful links related to the NWH Aerodynamics asset, including:
- Links to official documentation and tutorials
- Links to community forums and support channels
- Asset store links
- Current version information
This is the best place to check for the current version of the asset and access support resources.
Public API
Flight Data Properties (Read-only)
These properties provide real-time flight information updated during physics simulation:
Velocity and Speed
Airspeed (float, m/s) - Speed relative to surrounding air mass. Critical parameter for aerodynamic calculations as lift and drag depend on airspeed, not ground speed.
- Typical values: Stall 15-25 m/s, cruise 50-100 m/s, fast aircraft 125-250 m/s
AirspeedKTS (float, knots) - Airspeed converted to nautical knots for display purposes.
RateOfClimb (float, m/s) - Vertical speed; positive indicates ascending, negative indicates descending.
RateOfClimbFtMin (float, feet/minute) - Vertical speed converted to feet per minute for instruments.
Attitude and Orientation
Heading (float, degrees) - Compass heading (0-360°) based on aircraft's forward direction. Used by navigation instruments.
Pitch (float, degrees) - Nose-up attitude angle (-90° to 90°). Positive values indicate nose-up pitch.
Roll (float, degrees) - Bank angle (-180° to 180°). Positive values indicate right wing down.
Yaw (float, degrees) - Sideslip angle relative to velocity vector. Indicates deviation from flight path.
Aerodynamic Parameters
AngleOfAttack (float, degrees) - Angle between aircraft's longitudinal axis and relative airflow. Critical for lift generation and stall behavior.
- Normal flight: 2-8°
- Maximum lift: 12-16° (varies by airfoil)
- Stall angle: 16-20° for most aircraft
GlideRatio (float) - Ratio of horizontal to vertical speed in gliding flight. Higher values indicate better glide efficiency.
Position
Elevation (float, meters) - Altitude above reference level. Accounts for floating origin offset if present.
ElevationFt (float, feet) - Altitude converted to feet.
Ground Contact
- LandingGearTouchingGround (bool) - True if any landing gear wheel is in contact with ground.
Events
- OnCollision (CollisionEvent) - Triggered when aircraft collides with objects. Receives the Collision information for custom handling.
Flight Data Calculations
UpdateFlightData()
Called automatically each FixedUpdate, this method recalculates all flight parameters:
// Example: Access flight data in a script
float speed = aircraftController.Airspeed;
float altitude = aircraftController.Elevation;
float aoa = aircraftController.AngleOfAttack;
if (aircraftController.AngleOfAttack > 18f)
{
// Aircraft approaching stall
Debug.Log("Stall warning!");
}
The calculations use:
- Airspeed: Magnitude of velocity vector (aircraft velocity relative to air)
- Angle of Attack: Signed angle between velocity vector and forward direction
- Heading: Compass bearing from 2D forward direction
- Pitch/Roll: Derived from local Euler angles with sign correction
- Yaw: Sideslip angle from velocity vector to heading
Integration with Subsystems
Aerodynamics
Control surfaces and airfoils query current airspeed and angle of attack to generate appropriate forces. The AircraftController provides this data through properties and direct access to flight parameters.
Input System
The input system consists of two components:
AircraftInputManager (per-aircraft):
- Attached to each aircraft automatically with AircraftController
- Retrieves input from scene-level input providers
- Stores and distributes input states to control surfaces
- Can be manually controlled via script for AI aircraft
- Properties: Throttle, Ailerons, Elevator, Rudder, Flaps, Landing Gear, etc.
Input Providers (scene-level, shared):
- Scene-wide classes that capture raw input (keyboard, gamepad, mouse, touch, etc.)
- Implement base classes:
AircraftInputProviderBase(aircraft-specific),SceneInputProviderBase(general) - Examples:
InputManagerSceneInputProvider,InputSystemSceneInputProvider,MobileSceneInputProvider - All aircraft/vehicles in scene read from available providers
- Multiple providers can coexist (primary and fallback input methods)
- Automatically discovered and used by all input managers in the scene
Propulsion
Engines access current airspeed and altitude through the AircraftController for fuel consumption and performance calculations. Engine thrust vectors are applied to the Rigidbody through the propulsion system.
Instruments
Flight instruments (airspeed indicator, altimeter, attitude indicator, heading indicator, turn coordinator, vertical speed indicator) continuously read the AircraftController's flight properties to update displays.
Fuel System
The fuel manager monitors engine consumption and updates the center of mass through VariableCenterOfMass as fuel burns, affecting aircraft weight and balance.
Landing Gear
Landing gear components check LandingGearTouchingGround and collision events for ground contact detection and landing dynamics.
Physics Timestep (High Speed Performance)
The aerodynamics system performance and stability depend critically on the physics simulation timestep (FixedDeltaTime). At high speeds, aircraft can stall and become unstable if the physics timestep is too large.
Recommended Settings:
Low speed flight (< 50 m/s): Default 0.02s (50Hz) is acceptable
- Typical slow aircraft, ultralights, helicopters
- 0.02s timestep provides sufficient accuracy
Normal speed flight (50-100 m/s): Use 0.01s (100Hz) for smooth, stable behavior
- Typical general aviation aircraft
- Minimum recommended for reliable flight
- Provides good balance between stability and performance
High speed flight (> 100 m/s): Use 0.005s (200Hz) or lower for stability
- Fighter jets, fast aircraft, commercial aircraft
- Essential for avoiding sudden stalls during control surface direction changes
- The higher the speed achieved by the aircraft, the lower the physics timestep should be
Setting Physics Timestep:
- Go to Project Settings > Time > Fixed Timestep
- Set to desired value:
- 0.02 for low-speed flight
- 0.01 for normal flight (recommended default)
- 0.005 for high-speed flight
- 0.002-0.005 for supersonic speeds or very aggressive maneuvers
Why This Matters: During sudden control surface direction changes at high speeds, the aircraft experiences rapid acceleration changes. If the physics timestep is too large, the simulation can miss critical state changes, causing the aircraft to stall or behave unexpectedly. Reducing the timestep ensures more accurate force calculations and more responsive control feedback.
Performance Impact: Smaller timesteps (higher update rate) increase CPU load. Monitor frame rate when adjusting:
- Desktop: Can typically handle 200Hz+ physics
- Mobile/VR: May be limited to 100Hz or lower
- Large scale worlds: Consider impact on overall performance
Common Usage Patterns
Accessing Flight Data
AircraftController aircraft = GetComponent<AircraftController>();
// Read current flight parameters
Debug.Log($"Altitude: {aircraft.ElevationFt} ft");
Debug.Log($"Airspeed: {aircraft.AirspeedKTS} kts");
Debug.Log($"Rate of Climb: {aircraft.RateOfClimbFtMin} ft/min");
Debug.Log($"Attitude: {aircraft.Pitch}° pitch, {aircraft.Roll}° roll");
Detecting Stall Conditions
if (aircraft.AngleOfAttack > 16f && aircraft.Airspeed < 25f)
{
// Aircraft in stall condition
audioSource.PlayOneShot(stallWarningSound);
}
Detecting Ground Contact
if (aircraft.LandingGearTouchingGround)
{
// Apply landing dynamics, reduce speed, etc.
aircraft.GetComponent<Rigidbody>().drag = 0.5f;
}
Handling Collisions
aircraft.OnCollision.AddListener((collision) =>
{
if (collision.relativeVelocity.magnitude > 20f)
{
// High-speed crash; trigger damage system
audioSource.PlayOneShot(crashSound);
}
});
Monitoring Flight State
void FixedUpdate()
{
if (aircraft.RateOfClimb > 5f)
{
// Ascending at good rate
climbIndicator.SetActive(true);
}
if (aircraft.Heading > 270f && aircraft.Heading < 360f)
{
// Heading is north-northwest
}
}
Configuration and Setup Examples
Scene Setup
Before setting up any aircraft, ensure your scene has at least one Input Provider:
Input Providers (choose one or more):
- InputManagerSceneInputProvider - For Unity's legacy Input Manager (keyboard, gamepad)
- InputSystemSceneInputProvider - For new Unity Input System (recommended for modern projects)
- MobileSceneInputProvider - For mobile touch input
These are scene-level and shared among all vehicles. Each aircraft will automatically get its own AircraftInputManager when you add the AircraftController component.
Setting Up a Cessna-like Aircraft
- Create aircraft geometry (fuselage, wings, tail meshes)
- Add Rigidbody (mass ≈ 1200 kg, constraints: none)
- Add AircraftController component (automatically adds AircraftInputManager)
- Add control surfaces:
- Main wing: Aileron control surfaces
- Horizontal stabilizer: Elevator control surfaces
- Vertical stabilizer: Rudder control surface
- Add engine (Piston Engine + Propeller Propulsor)
- Add landing gear (3-point configuration)
- Add fuel tanks and fuel manager
- Add flight instruments
- Use Aircraft Setup Wizard for automatic inertia configuration
- Ensure an Input Provider exists in scene (InputManagerSceneInputProvider or InputSystemSceneInputProvider)
Setting Up a Fighter Jet
- Similar steps as above but with:
- Higher mass and inertia values
- Jet propulsion (Turbine Engine + Jet Propulsor)
- High-speed performance: Set Fixed Delta Time to 0.005s (200Hz)
- More responsive control surface curves
- Enhanced effects system
Flight Dynamics and Physics
Aerodynamic Force Generation
The AircraftController coordinates force generation from multiple sources:
Lift and Drag:
- Airfoils generate lift based on angle of attack and airspeed
- Drag is calculated from airspeed and drag coefficient
- Net forces are applied to the Rigidbody through forces and torques
- Total aerodynamic force depends on all active airfoil sections combined
Control Surface Input:
- Ailerons affect roll through differential lift on wings
- Elevators affect pitch through elevator surface deflection
- Rudders affect yaw through vertical stabilizer forces
- Flaps modify lift curve and increase drag for takeoff/landing
Engine Thrust:
- Engines produce thrust based on throttle input
- Propulsors apply thrust vector to aircraft
- Thrust directly affects airspeed and climb rate
- Engine performance varies with altitude and airspeed
Center of Mass Management
The VariableCenterOfMass component automatically adjusts the aircraft's center of mass based on:
- Fuel consumption from fuel system
- Payload distribution
- Cargo/weapon loading
This affects:
- Aircraft stability and handling characteristics
- Stall speed (increases with weight)
- Turn performance (heavier = larger turn radius)
- Climb rate (reduces with weight)
Note: VariableCenterOfMass is part of NWH Common. For more information, see NWH Common - Variable Center of Mass.
Advanced Topics
Extending AircraftController
The AircraftController can be extended through:
Inheritance:
public class CustomAircraft : AircraftController
{
public override void FixedUpdate()
{
base.FixedUpdate();
// Add custom physics or behavior
}
}
Component Composition: Create custom MonoBehaviours that reference the aircraft:
public class DamageSystem : MonoBehaviour
{
private AircraftController aircraft;
void Start()
{
aircraft = GetComponentInParent<AircraftController>();
}
void Update()
{
// Monitor aircraft state and apply custom logic
}
}
Event Subscription: Hook into aircraft events:
aircraft.OnCollision.AddListener(HandleCrash);
Integrating Custom Systems
To integrate custom systems with AircraftController:
Reference the Aircraft:
- Use
GetComponentInParent<AircraftController>() - Or assign directly in inspector
- Use
Read Flight Data:
- Query Airspeed, Heading, Pitch, Roll, etc.
- Use RateOfClimb for vertical flight data
- Access AngleOfAttack for stall detection
Modify Aircraft Behavior:
- Apply forces to the Rigidbody directly if needed
- Modify control surface inputs through AircraftInputManager
- Subscribe to events for reactive behavior
Update Game Systems:
- HUD displays update based on flight data
- Audio systems respond to airspeed and engine state
- AI systems use flight data for decision-making
Handling Edge Cases
Stall Behavior:
- Monitor AngleOfAttack and Airspeed
- Apply recovery procedures (lower nose, increase power)
- Implement stall warning systems
Inverted Flight:
- Roll angle can exceed ±90°
- Pitch can reach ±90° (inverted vertical)
- Negative lift at high angles of attack
- Control effectiveness changes when inverted
Supersonic Flight:
- Very high airspeeds require lower Fixed Timestep
- Shock waves and compressibility effects not included in basic physics
- Consider control surface saturation and lag
Floating Point Precision:
- Use ShiftingOrigin for large worlds
- AircraftController.Elevation accounts for origin offset
- Flight data remains accurate across world shifts
Note: For comprehensive information about ShiftingOrigin including setup, networking, and best practices, see NWH Common - Shifting Origin.
Troubleshooting Common Issues
Aircraft Won't Fly
No airflow generated:
- Check Rigidbody has non-zero mass
- Verify control surfaces are assigned
- Confirm airfoils are present and configured
Airfoils not generating lift:
- Verify airfoil angle of attack curves are configured
- Check control surface input is being registered
- Ensure aircraft is moving (airspeed > 0)
Physics unstable or erratic:
- Reduce Fixed Timestep (0.01 or lower)
- Check Rigidbody mass is reasonable
- Verify no extreme inertia tensor values
- Ensure collision geometry is valid
Aircraft Uncontrollable
Control surfaces not responding:
- Verify input is reaching AircraftInputManager
- Check control surface deflection ranges
- Confirm control surface is assigned to aircraft
Aircraft spins out or stalls:
- May be inverted flight - check Roll/Pitch values
- Reduce airspeed to recover
- Increase pitch to increase angle of attack
- Reduce Fixed Timestep for smoother behavior
Overshooting turns:
- Reduce control input sensitivity
- Use damping/smoothing on control inputs
- Verify inertia tensor values (increase for more stable handling)
Unrealistic Flight Behavior
Aircraft feels too heavy/light:
- Adjust Rigidbody mass
- Verify engine thrust is adequate
- Check airfoil configurations
Stall handling unrealistic:
- Configure stall angle in airfoil settings
- Implement custom stall recovery logic
- Monitor AngleOfAttack for stall warnings
Speed feels wrong:
- Check environment wind settings
- Verify engine thrust values
- Confirm drag calculations are correct
Related Classes
Vehicle- Base class providing Rigidbody management and update loopAircraftMonoBehaviour- Base class for aircraft components with automatic parent referencingAircraftInputManager- Handles input capture and distributionVariableCenterOfMass- Manages dynamic center of mass adjustmentsAirfoil- Aerodynamic surface generating lift and dragControlSurface- Control surface types (aileron, elevator, rudder, flap)AircraftEngineBase- Base for piston and turbine enginesLandingGear- Landing gear wheel with ground detectionAircraftFuelManager- Manages fuel consumption and center of mass updates