Should I multiply every physics calculation by delta to make them frame rate independent? Is it even necessary?

Godot Version

4.4

Question

So, as I finished up my basic movement system, I got told something every important: I should multiply my physics events by delta so their not frame-rate dependent.

I’m now wondering how far this goes.

For example, my current simple jump function:

func jump() -> void:
	
	if is_on_floor():
		velocity.y = Jump_Force

Should I multiply my Jump_Force (The jump height) by delta?

Example:

func jump(delta:float) -> void:
	
	if is_on_floor():
		velocity.y = Jump_Force * delta

I just want this clarified for posterity.

Edit: I’m looking at the Godot documentation’s guide on physics. It says the following:

I’m about 95% sure I need to add delta, but I’m going to wait for a response.

If you’ve got a one-shot impulse force, you don’t want to scale by delta. If you’ve got a force that’s applied proportionally over time, you want to scale by delta.

2 Likes

I don’t think velocities need to be multiplied by delta, as they are a mesure of space over time. I believe the engine already takes frame duration into consideration when computing movement.

However, if you were to directly change the coordinates of your elements, you should use delta to ensure frame independency. Eg:

func move_object(delta:float) -> void:
	position += my_velocity *delta

The delta above is needed as you are updating the position every frame rather than telling Godot what the velocity is and letting it compute how the object should move.

I would suggest making an experiment and artificially setting different frame rates to see what happens.

Please someone kindly correct me or confirm whether I am wrong or not!

1 Like

@hexgrid

This makes sense. A one-time jump impulse isn’t multiplied by delta, but gravity is.

func apply_gravity(delta: float) -> void:
	
	if not is_on_floor():
		velocity.y -= Gravity * delta

Good to know.

I’m actually planning to rework my jump function into it’s final version. Splitting the function into start_jumping and stop_jumping. Where the former adds a upward force frequently until a set time or when the the jump button is released (triggering stop_jumping). Now, I know what to do.

move_and_slide() uses the CharacterBody’s velocity value and takes delta into account. move_and_collide() does not, and you would need to multiply whatever velocity you are passing into that function by delta.

If you’re you’re just using move_and_slide() you do not need to multiple by delta. However, if you are altering the velocity over time (aka acceleration) then you do need to take delta into account. Gravity counts as acceleration as well.

1 Like

no. that is a unity problem only. :grinning:

use _physics_process for physics, it is not frame dependent, it runs at a constant 60 fps.
rename delta to _delta to stop the warnings.

no. velocity / move_and_slide uses delta internally in godot 4.
also you are doing a single jump, delta is only useful over more than one frame.

is_on_floor() is also dependent on physics, so you want to run it on _physics_process to avoid bugs (if the player has force applied but the physics tick hasn’t happened yet so it could add multiple times)

the documentation is outdated and some parts are only relevant to godot 3.

_process is for things that must run every frame, so we can use it for graphics things like showing and hiding a quad with a shader, it can also be used to move nodes independent of the physics engine, we are talking about merely visual elements.

the delta idea comes from unity where they don’t have a physics_process.

Unity has a FixedUpdate function, doesn’t that work similarly to _physics_process()?

Anyway, delta is still needed for acceleration.

from the unity docs:

    private void Start()
    {
        controller = gameObject.AddComponent<CharacterController>();
    }

    void Update()
    {
        groundedPlayer = controller.isGrounded;
        if (groundedPlayer && playerVelocity.y < 0)
        {
            playerVelocity.y = 0f;
        }

        Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        controller.Move(move * Time.deltaTime * playerSpeed);

        if (move != Vector3.zero)
        {
            gameObject.transform.forward = move;
        }

        // Makes the player jump
        if (Input.GetButtonDown("Jump") && groundedPlayer)
        {
            playerVelocity.y += Mathf.Sqrt(jumpHeight * -2.0f * gravityValue);
        }

        playerVelocity.y += gravityValue * Time.deltaTime;
        controller.Move(playerVelocity * Time.deltaTime);
    }

this is the example character controller script in the unity docs.
maybe it’s a bad idea to run fixedUpdate, maybe they didn’t think about it. the point is we were made to multiply everything by delta, in every tutorial, in the docs.
but also, FixedUpdate is dependent on game speed which can be changed, so if it was 0 it would not run. and this was done to pause games.

godot doesn’t have that problem because you can pause, with the process mode pause, and control physics speed independently. :grinning: