I would model the plane with a little more direct simulation. I would also use forces almost exclusively, to simulate the same behavior that aerodynamics applies.
If it’s a propeller plane, with traditional wings and tail, maybe there are six points on the plane that need consideration: left and right wing/aileron, left and right stabilizer/elevator, rear stabilizer/rudder, and front nose propeller.
Each of these add a certain amount of force (typically upwards, or for rudder, sideways) as well as a certain amount of drag (more drag the more control is applied.)
The force is proportional to airspeed (as well as square of airspeed, if you want to be precise.)
The propeller adds thrust backwards (force forwards,) but also adds torque because of the rotation of the propeller.
Finally, the plane itself adds some drag that’s proportional to airspeed (and square of airspeed, if you want.) This drag also has a function of attitude – the more pitched the plane is compared to its movement vector, the larger the drag is. This is generally a non-linear function, but for arcade purposes you can model it as something like square root of dot product.
Note that the physical body properties matter, too. A little linear damping, a little rotational damping (very important!) and the right amout of mass (for inertia) is important.
Friction isn’t particularly important. Rolling wheels have low friction, and the air drag is friction with “air” that’s always there, which is different from the contact friction modeled by the built-in physics engine.
Thus, you can model the airplane as a rigid body, with the following simulation happening each tick:
Body.AddForceAtLocalPosition(
Plane.LeftAileronPosition,
Plane.Airspeed * ((Plane.WingLift + Control.AileronTiltRight * Plane.AileronControlScale) * Plane.UpOrientation +
Abs(Control.AileronTiltRight) * Plane.AileronControlDrag * Plane.BackOrientation));
Body.AddForceAtLocalPosition(Plane.RightAileronPosition,
Plane.Airspeed * ((Plane.WingLift - Control.AileronTiltRight * Plane.AileronControlScale) * Plane.UpOrientation +
Abs(Control.AileronTiltRight) * Plane.AileronControlDrag * Plane.BackOrientation));
Body.AddForceAtLocalPosition(Plane.LeftStabilizerPosition,
Plane.Airspeed * ((Plane.StabilizerLift + Control.ElevatorPitchDown * Plane.ElevatorControlScale) * Plane.UpOrientation +
Abs(Control.ElevatorPitchDown) * Plane.ElevatorControlDrag * Plane.BackOrientation));
Body.AddForceAtLocalPosition(Plane.RightStabilizerPosition,
Plane.Airspeed * ((Plane.StabilizerLift + Control.ElevatorPitchDown * Plane.ElevatorControlScale) * Plane.UpOrientation +
Abs(Control.ElevatorPitchDown) * Plane.ElevatorControlDrag * Plane.BackOrientation));
Body.AddForceAtLocalPosition(Plane.RudderPosition,
Plane.Airspeed * ((Control.RudderTurnRight * Plane.RudderControlScale) * Plane.LeftOrientation +
Abs(Control.RudderTurnRight) * Plane.RudderControlDrag * Plane.BackOrientation));
Body.AddForceAtLocalPosition(Plane.PropellerPosition,
(Control.PropellerThrust * Plane.PropellerControlScale) * Plane.ForwardOrientation);
Body.AddTorqueAtLocalPosition(Plane.PropellerPosition,
(Control.PropepperThrust * Plane.PropellerTorqueScale) * Plane.ForwardOrientation);
float PitchDeltaUp = Vector3.DotProduct(Plane.UpOrientation, Vector3.Normalize(Plane.VelocityVector));
float SlewDeltaRight = Vector3.DotProduct(Plane.RightOrientation, Vector3.Normalize(Plane.VelocityVector));
// Drag is expressed as an off-center force, because it works to both "right"
// the plane, and "brake" the plane.
Vector3 DragPosition = Plane.CenterLocation +
PitchDeltaUp * Plane.DeltaUpDragTorqueScaling * Plane.BackwardOrientation +
PitchDeltaRight * Plane.DeltaRightDragTorqueScaling * Plane.RightOrientation;
Body.AddForceAtLocalPosition(DragPosition,
Plane.Airspeed * (Plane.AirspeedDrag + Sqrt(Abs(PitchDeltaUp)) * Plane.UpDrag + Sqrt(Abs(SlewDeltaRight)) * Plane.RightDrag));
That might look like a lot of terms, but it’s really the minimum you could get away with to actually model the controls of an airplane.
Also, getting all the tuning constants in the right order of magnitude needs a little bit of tuning, but you could probably calculate what it “should be” using regular physical formulas first.
Finally, I probably got the vector function names wrong – I’m not at the IDE right now to look them up, and it’s been a bit since I last did this. But hopefully you can translate!
… thinking about it, this feels like something that might actually be worthwhile on the marketplace …