Implementing drag(air resistance) when falling for natural falling


I was going to post in my previous topic but thought to create a new one because this is a completely different problem.

Project Link:

What I am trying to achieve is smoother falling so when a player enters the falling state a force is applied and as the player falls even more it reaches a max force (terminal velocity). I understand that drag in Playcanvas translates to linearDamping, but 0 linearDamping on -9.8 gravity is still really slow when falling. I want to keep my global gravity as -9.8 while simulating a smooth falling. I did not want to just apply a constant force on the Y axis when the player was falling as that is not natural. I made a picture of what I am trying to achieve below.

So far the code I wrote to calculate this is:

if (this.playerFalling) {
        let airResistance = 10000;
        let linearVelocity = this.entity.rigidbody.linearVelocity;
        let fallVelocity = linearVelocity.normalize().y * airResistance * dt;
        let coeff = (1 - dt * airResistance);
        let force = (fallVelocity / coeff) * this.entity.rigidbody.mass;
        this.entity.rigidbody.applyForce(0, fallVelocity + force, 0);
        console.log('velocity: ' + linearVelocity.y);
        console.log('coeff: ' + coeff);
        console.log('force: ' + force);

The terminal velocity appears to be working (atleast I think it does as the velocity increases from a value between -0.0 and -1 which then caps as the max). Below is a screen shot of debugging the velocity value which finally caps at -1 once it hits the terminal velocity.


But the problems are:

  • The fall starts off really slow. So when the player enters the falling state it floats down and then gets faster over time slowly. I want the terminal velocity to be achieved quicker but without breaking jumping.
    So instead of this: jump → float → fall → fall faster
    I want it to be: jump → fall → fall faster

  • I am currently having to enter airResistance to 10000+ which does not seem like an optimal value (it’s too large but somehow works at the moment).

I feel like I am very close somehow but can’t figure out the last step, or I might have made some miscalculations. If somebody could check the code/project and help me simulate a nice natural falling at -9.8 I would really appreciate it!

You don’t need to do anything extra here. Ammo will calculate the resulting force vector for you automatically. There is no magic here - it follows the Newton’s first and second laws. If you have a 100 kg object and you apply an upward impulse to it, this is how it would behave in real life as well.

It is only your perception that it falls too slow. If you feel your game needs to have more speed, you can increase the gravity, or apply a constant downward force on the object while increasing the upward impulse power.


I think you are right I guess it must be my perception that it feels too slow. I played around with the mass and jump force + air resistance and it works a bit better then what I originally had - or maybe its completely the same and just feels like that to me.

I want to experiment with something: is there anyway to get the state of when the rigidbody rises after an impulse? So for example when you press space grounded = false then after that the player rises, after the rise ends (velocity.y < -1 = true) and therefore falling = true. Is there anyway to get the state between grounded and falling? Its the time between pressing space to jump and falling. → So whilst the impulse happens.

Hi @nasjarta,

The body will rise as long as it’s linear velocity in the Y axis is > 0. So you can monitor that directly after the jump starts.

1 Like

Ohhh how did I not know that lol. Its as easy as swapping velocity.y < 0 to velocity.y > 0

I currently use velocity.y < -1 instead of 0. When using 0 it returns true even when moving around or standing still and not jumping even though im only watching the y axis. Any idea why that happens?

Yes velocity on the Y axis can increase when moving around even on a flat surface e.g. when there is a bump with another object the object may react and release its energy in all directions.

But since you know the instant at which the player presses the jump button you can start monitoring from that moment until > 0 returns false.


So in this case only to detect jumping/falling then -1 would suffice rather than 0.


1 Like