Alright so I haven’t made something like this myself but I am taking highschool physics so I think I can chip in a thing or two.

I would first make sure to keep everything simple by keeping all velocities, forces, etc in roblox’s vector3 form - its easier to work with and explain. This is how I would make a very simple aerodynamic model, and I am not considering any forces related to the rotation of the “bird”, because thats too difficult for me where I am at now.

A simple glider has 4 forces being applied to it: weight, thrust, lift and drag

You can define a variable somewhere in the code and calculate these all constantly, adding them up all to one vector.

The first force, weight, is the easiest to calculate - in roblox, you have no celestial body you are pulled by gravity towards, you just go down, so you would have a force of (0, -mass * gravity, 0).

Thrust can be divided into two sections: a vertical, and a horizontal component. How much you move down, and how much you move forwards. Thrust is converted from the object pushing air backwards as it moves down, which can be based on the angle of descension: this could be more complex but in a simple system like a glider/bird for a game, you can can just use arbitrary figures. The thing to remember here is that as thrust pulls you forwards, you will stop descending as fast. Without winds, a propeller, or another means to push you forwards, you won’t be able to generate more thrust than you have falling velocity. Lets say you want to calculate thrust, you need to first calculate how much the Y-component is slowing down vertically using the angle of descent, and then assume you are moving forwards a percentage of that (you could decide you want perfectly efficient beings and simply use that value, but in all real systems you will be losing useful energy.) You will first need to know the angle of descent, and the current velocity of the bird. The angle of descent the pitch (rotation on the X-axis), which you can learn how to extract here: https://developer.roblox.com/articles/Euler-Angles, (roblox is weird, pitch,roll,yaw = x,y,z, this confused me at first), and straight down. Simply let ad (angle of descent) = pitch from euler angles. You can sine this value and use it as a fraction to decide how much of the vertical component in the velocity should stay, letting current velocity = a, new velocity = b, b.y = `a.y * math.abs(sin(ad))`

, you are using an absolute value because we don’t want to flip the signs and send the player flying in the wrong direction. Forward component = `(1-sin(ad))*a.y`

this is a scalar, so you should use the lookvector of the glider to determine the force being applied forwards, letting lookvector = c, you should get rid of the y component of the look vector as you are moving forwards, final calculation `b = a - v3(0,(1-abs(sin(ad)*a.y)),0) + v3(c.x,0,c.z)*(1-sin(ad))*a.y`

, in a script this would look like this:

```
thrust = -Vector3.new(0,(1-math.abs(math.sin(ad))*a.y,0) + Vector3.new(c.x,0,c.z)*(1-math.sin(ad))*a.y
velocity = velocity + thrust
```

This is a perfectly efficient conversion and will allow you to just float in the air, and you probably don’t want this, so you could arbitrarily decide for your birds that they will always keep atleast 20% of their fall velocity, and only 80% of the converted kinetic energy is useful, giving you this code:

```
thrust = -Vector3.new(0,(1-math.abs(math.min(math.sin(ad),0.2)*a.y),0) + Vector3.new(c.x,0,c.z)*(1-math.abs(math.min(math.sin(ad),0.2)))*a.y*0.8
```

There are ways to better calculate exactly just how wind-resistant and thus efficient different models at different angles should be, but this is fine for a game.

Lift is much easier, as you aren’t actually propelling forwards using mechanical movement, you are just magically applying an up force as the wings flap. This should at least be able to counteract the maximum possible down force, which is mass * gravity, so just remember when choosing a figure, magnitude of lift > mass * gravity. Lift could actually be less than or equal to the down force, however, you likely want the ability to fly straight up.

What you might notice is that you do not actually have to apply a forwards force other than thrust - when moving up, or down, you will also move forwards. What you will need is a force counteracting thrust, as currently there is nothing slowing you down, you can accelerate indefinitely. This is where drag comes in. Drag is **always** going to counteract the existing velocity of an object, and is proportional to the velocity squared - as you speed up, you eventually reach a point called the terminal velocity, which is the maximum possible velocity you can get with the forces you are exerting in the substance you are moving in. In space there is no drag, but we aren’t in space. The force of drag can be, in a game, calculated using the negative velocity squared of the body multiplied by an arbitrary figure. `DragForce = -(Velocity^2) * DragValue`

Again, this could be more complex, but this is really all you need. You can use some more math to dynamically calculate the surface area but keeping this simplicity is okay in a game. If you want different drag values for the horizontal and vertical components, so you can fall at a different maximum speed than you move down, then you can just use this:

```
DragForce = -Vector3.new((Velocity.X^2)*DragValueH,(Velocity.Y^2)*DragValueY,(Velocity.Z^2)*DragValueH)
```

If you want to find the drag values for a particular terminal velocity, so that you can only move at a certain speed, you can arrange the formula for all the forces MaxForce = Weight + Thrust + Lift + Drag, put as much values as you can, and then solve for what’s missing algebraically.

After calculating these four forces, you can simply add them all together to get one mega-equation like below:

```
force = Vector3.new(0,-mass*gravity,0) -Vector3.new(0,(1-math.abs(math.min(math.sin(ad),minimumDownForceKeptValue)*Velocity.y),0) + Vector3.new(c.x,0,c.z)*(1-math.abs(math.min(math.sin(ad),minimumDownForceKeptValue)))*Velocity.y*thrustEfficiencyValue + Lift -Vector3.new((Velocity.X^2)*DragValueH,(Velocity.Y^2)*DragValueY,(Velocity.Z^2)*DragValueH)
```

You can use a bodyforce object mover here https://developer.roblox.com/api-reference/class/BodyForce and set the force value to whatever you manage to calculate on renderstepped.

EDIT: I used abs to get an absolute value on the sine of ad in the thrust, this means you’ll go forwards the same when you are falling and going up. It would be more realistic to not use an absolute value, so you are actually pushed back as you go up, making dives when you go down seem relatively faster.