How to implement smooth, fair, universal and latency free jumping in 3D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By denexter3

EDIT: 8 hours passed, got an “answer” which didn’t even answer anything, and a -1 for using move_and_slide in _process - at this rate the entire Godot community will burn me to ashes for doing something that is perfectly acceptable by devs.
Anyway, I found a good fix for it, just use this instead.

It basically makes all jumping take place without move_and_slide, so delta can be applied where it actually makes sense, which is at the gravity handling part.

How it works right now

EDIT: YES. I do physics calculations in _process, and I won’t change it, unless there is a way to make it lag free.

I implemented all movement, but only jumping has some problems.
To make it smooth I use this expression:

velocity = move_and_slide(lerp(velocity, desired_velocity, friction), upwards_direction)

I only set desired_velocity, this makes all moment as smooth as friction want’s it to be.

To make it fair I simply set friction = 10 * delta, which will make everything accelerate, and deaccelerate at the same speed no matter how fast the game runs.

I made it latency-free, and universal by just planting everything in _process, as _physics_process would result in jittery movement and latency on monitors with refresh rate higher than 60.

My entire player.gd can be found here.

The jumping
I simply use this line to get myself to speed:

desired_velocity.y += 40 * mvmnt_amplifier

And this handles gravity, and deacceleration:

desired_velocity=Vector3(0, gravity_strength*10, 0)

All of it results in smooth, and latency free jumping expirence, with one problem.

The problem
At 144 fps I jump ~4.5 units, when at 30 I jump whopping ~51.3 units high.

:bust_in_silhouette: Reply From: timothybrentwood

All movement should be done within physics_process() to get consistent results across all frame rates and have collisions work properly.

To fix your jitter issue there is a setting in Project > Project Settings > General > Physics > Common > Physics Jitter Fix that you can adjust. You can adjust this at runtime by adjusting the Engine.physics_jitter_fix property. It seems like you’ll want to detect (or have user input in a settings menu) the monitor’s refresh rate and adjust that value depending on it. You just have to play around with your game on different refresh rates to find a value that’s appropriate for each.

I believe your game will crash if you are holding down the right or left inputs when you start it up. As facing_direction is only allocated as a Vector3 and doesn’t have a value assigned to it, but I’m not sure. IMO your deg2rad(90) and deg2rad(-90) should be constants since you’re potentially using them every frame.

This doesn’t answer anything, at all. And isn’t true.

Holding player movements in _physics_process will inherently introduce input lag, and the only way to get rid of it is by raising the _physics_process fps to match _process fps, which will make it inconsistent, and waste resources.

physics_jitter_fix doesn’t work in 75% of cases, and the only way to work with it is by using the smoothing plugin. Which won’t solve the input lag issue.

Holding things inside _physics_process doesn’t make them magically become consistent, that’s simply not true. If you change its refresh rate they will become faster or slower, if you don’t use delta WHICH IS MY GODDAMN QUESTION.

I believe your game will crash if you are holding down the right or left inputs

Vector3 defaults to (0, 0, 0), check the docs.

IMO your deg2rad(90) and deg2rad(-90) should be constants

Sure, that can give me like +2 fps.

Look at Source engine, even GoldSRC, all of them have consistent movement, no input lag at high FPS, almost perfect physics, and I just wan’t to make something like this in Godot.
I know Godot can do it, I just don’t know how to approach this problem.

denexter3 | 2021-06-02 16:45

Please keep your comments constructive as per the code of conduct.

Calinou | 2021-06-03 20:09

:bust_in_silhouette: Reply From: denexter3

Yo, it’s OP.
The fix is here, pretty much with all of the movement being what I always wanted.

Just copy this entire thing, and paste it to your player node - it must be as KinematicBody.
All of the calculations are done in _process, but you can simply copy-paste it to _physics_process if you don’t care about input lag.

I looked everywhere on the web, with barely any answer saying how to get jumping here, and none having all of the movement smoothed out.

PS: Don’t forget to make deg2rad(-90) and deg2rad(90) as constants, a random kitten gets 1% less daily care every time you call this function.

:bust_in_silhouette: Reply From: Calinou

If you want physics to remain stable while avoiding jittering, you need to use physics interpolation. This will likely be a built-in feature in Godot 4.0, but in the meantime, you can use lawnjelly’s smoothing-addon.

If low input lag is critical, you can increase the Physics Fps in the Project Settings while keeping the smoothing add-on. Just remember that as the physics FPS increases, there are diminishing returns in doing so (in terms of input lag reduction).

When using the smoothing add-on, remember to disable the physics jitter fix by setting it to 0 in the Project Settings.