Advice on airplane physics

I am building a simple airplane like in Pilotwings 64 (video) and am working to balance the different forces.

The airplane is 100 kg and during takeoff I use the Add Force node to apply a forward thrust of 70000.0. When the airplane reaches 50 km/h I apply an upward force of 100010.0 which gives a gentle lift.

The airstrip has a Physics materials with a friction of 0.2, and the plane has a physics material with friction of 0.1 and density of 2.0.

The main challenge is how to rotate the airplane. Using a torque on the Z axis works well to rotate the airplane, but the airplane takes a long time to actually change it’s velocity. This is fixed by increasing the linear damping, which allows the plane to more quickly change it’s direction. However, increasing the linear damping has the undesired effect that the airplane takes a long time to build speed during takeoff.

My question is how do I balance the friction force of the materials, linear damping on the airplane, and forces applied to the airplane(Add Force node) to achieve a decent simulation? Any general advice would be welcome.

Ultimately, the key to achieving a good simulation is to experiment, observe the results, and adjust the parameters until you achieve the desired behavior. Don’t be afraid to try different approaches or seek out additional resources, such as online tutorials or forums.

In general, it’s a good idea to start with conservative values for these parameters and gradually adjust them until you achieve a simulation that feels realistic and satisfying. You may also want to experiment with different force and torque values to see how they affect the airplane’s motion.

First, it’s important to understand the basic physics principles that govern the motion of your airplane. For example, the force of friction between the airplane and the airstrip will act to slow down the airplane’s forward motion, while the force of lift generated by the upward force will act to counteract gravity and keep the airplane in the air. Additionally, the torque on the Z axis will cause the airplane to rotate, but this will also affect the direction and speed of the airplane’s motion.

To balance these forces, you can experiment with adjusting the values of different parameters, such as the friction coefficients and linear damping. For example, increasing the friction coefficient of the airplane’s physics material will increase the force of friction and make it more difficult for the airplane to move forward, which could help to balance out the effect of the torque on the Z axis. Similarly, increasing the linear damping will make it easier for the airplane to change direction, but it will also slow down the airplane’s motion, so you’ll need to find a balance between these two factors.

Another approach is to use a physics engine that provides more advanced simulation features, such as aerodynamics modelling or more advanced friction models. This can give you more control over the simulation and allow you to achieve more realistic results. However, implementing physics is a nightmare as far as I know…

I also want to add: The physics system is based on real-world physics principles, but it also includes some simplifications and approximations to make it efficient and practical for real-time applications. This means that is not 100% reliable to a real-world mapping. While the physics simulation is based on real-world physics principles, it includes simplifications and approximations that may not perfectly match the behavior of real-world objects and interactions. Hence my recommendation to experiment and observe the results.

@EliasWick Thanks for the thoughtful reply. Your comments match my experience so far so that is reassuring and encouraging.

That game is probably full kinematic, or at least the rotations. I tried a similar project in ue4 without using kinematic rotations and it was very difficult to do inside a simulation. If you get tired of messing with the physics I would suggest not simulating physics for rotations. If you do get it working though I would love to see a vid of it:)

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 …

1 Like

@jwatte This is an excellent writeup, thank you. In particular this bit quoted below is something I had not considered but is no doubt key. The calculation you propose is indeed an intuitive way to model this for arcade purposes.

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.

The in-flight physics make sense but I have two follow up questions about taking off.

  1. Can you elaborate on what frictional properties to use for the plane and the runway? Currently I’m modeling the wheels as 3x spherical colliders with low friction. They do not roll, and instead just slide along the runway during takeoff.

  2. During takeoff I trigger a gentle upward force on the plane when the forward velocity gets above the 50 km/h threshold. This works, but in your opinion is there a better approach?

You could set friction to close to zero. Although, in the best of worlds, you have anisotropic friction – sideways, the friction is high; front/back, the friction is very low. (Like, 0.01 or something)

Regarding takeoff, assuming you model the lift force as some function of airspeed, you don’t need any particular additional boost; just get the plane to where the lift is strong enough.
To get a little more realism, you may want to make the airspeed-dependent lift increase with positive attitude, to simulate pitching up causing the plane to want to lift more. And then there’s flaps…

That being said, video from the game you linked looks like it’s not simulating flight at all.
One thing you could do is simply to turn off gravity, and determine for yourself what speed and lift you want the plane to have, in velocity space, not force space. Then drive the actor using velocities, rather than forces. This will be a lot more old-skool and a lot less physical, but if that’s the gameplay you want, then that’s what you can do.

@jwatte I like your suggestion about disabling gravity and working in velocity space and not force space.

In practice, are you suggesting using SetPhysicsLinearVelocity to model the effects of gravity, lift, thrust, etc? In the docs it says this about SetPhysicsLinearVelocity:

This should be used cautiously - it may be better to use AddForce or AddImpulse.

This gives me hesitation, and matches my intuition that directly setting velocity will interfere with the physics simulation.

Or, is there some other approach you had in mind?

If you set velocity directly, you may get problems if you actually collide with something.
As long as you’re free of collisions, you should be fine. This will give a very “arcade” kind of physics, which might be exactly what you want.

You can add listeners for collision/hit events, and update your own velocity calculation to bounce away from the collided plane. Easiest is to remove any component of velocity that moves into the inverse of the surface normal you collide with, BUT! There’s some gnarls with that if you wedge yourself into a narrow “V” crevice.

Another option is to save “recent known good non-collidiong position” and simply teleport to that position if you find that you’re colliding (and change velocity.)

Game physics really have two modes:

  1. Attempt to be as realistic as possible, accepting all the complexities of “real” physical dynamics combined with the imprecisions of collision detection and imperfect integrators.
  2. Attempt to set up all the velocities and positions the way you like it, and instead acceping all the impossibilities that can be caused by players, geometry, and your game rules disagreeing on reality.

Either way, it’s hacks all the way down :slight_smile: The hacks just look different depending on your goal.