Architecture¶
PFC is a custom flight model layered on top of Enfusion's rigid-body simulation. The engine integrates the
rigid body; PFC's scripts apply per-surface lift/drag and thrust via Physics.ApplyImpulseAt, plus
angular-rate damping to keep the airframe stable.
Built on Wheeled_Base.et¶
The reference Cessna inherits the vanilla Wheeled_Base.et. The wheeled simulation is neutralized - only
the suspension and wheel-bone visuals remain - so the inherited SCR_CarControllerComponent still handles
ownership transfer and grants the input context (CarContext) that the flight controller reads.
Flying on a car base has sharp edges
The vanilla car controls share keys with flight: the handbrake stays engaged because CarThrust is 0,
CarBrake is on S (= pitch back), and CarShift is on Q/E (= yaw). PFC neutralizes all of
these every frame. See Prefab Setup for the full list of
wheeled-sim settings that must be right, and Input & Controls for the key
de-conflicting.
Components¶
| Component | Responsibility |
|---|---|
PFC_FlightModel |
The flight model. Builds aero surfaces, applies per-surface lift/drag + thrust impulses, spools engine RPM, angular damping, wind/gusts, publishes instrument signals, debug draw. Runs on owner + server. |
PFC_FlightController |
Reads pilot input from CarContext, smooths it (slew-rate limited), exposes pitch/roll/yaw/throttle to the flight model, relays input to the server, and injects ground steering. |
PFC_NwkMovementComponent |
Replicates owner→proxy movement state (transform + velocity) so remote viewers see smooth motion. |
PFC_AeroSurface |
A single aerodynamic panel: given local airflow + air density, returns the lift+drag force. Pure math, no engine state. |
PFC_AeroSurfaceConfig |
Runtime aero parameters for one surface (chord, span, lift slope, stall, etc.). |
PFC_AeroSurfaceDef |
The editable surface definition placed in the prefab; builds a config and resolves its axes, handles X-mirroring. |
PFC_PilotUtil |
Helper to determine the local active pilot. |
Execution flow (per simulation tick)¶
EOnSimulate (owner / server only)
├─ PFC_FlightController.PollInput() → smoothed pitch/roll/yaw/throttle
├─ set each surface's flap deflection from its control axis
├─ guard against NaN / teleport-spike velocity (reset or clamp)
├─ RefreshWind() → steady wind + gradient + gusts
├─ for each surface: CalculateForce() → ApplyImpulseAt(surfacePos, force·dt)
├─ fuselage drag impulse
├─ spool engine RPM, apply thrust impulse at the centre of mass
├─ speed-scaled angular-rate damping
├─ compute normal G-load
└─ (owner, once registered) UpdateSignals() → instrument MP signals
EOnFrame (all peers)
├─ PFC_FlightController.ApplyGroundSteering() (also zeroes CarThrust/CarBrake/CarShift)
├─ UpdatePropellerVisuals() (owner/server from local RPM; proxies from replicated RPM signal)
└─ DrawDebug() (F6)
Authority model¶
EOnSimulatereturns immediately on a peer that is neither the owner nor the server, so the aerodynamic simulation only ever runs on the authoritative peer.- The owner publishes instrument signals; they replicate to everyone for free.
- Proxies receive replicated movement via
PFC_NwkMovementComponentand drive their own propeller spin from the replicated, normalized engine-RPM signal. OnTicksOnRemoteProxy()returnstrueso the component keeps ticking on proxies (needed for the local visual updates).
See Networking & MP for the replication and signal details, including the compression and boot-window pitfalls.