Variable jump height with character controller and fps

I’m trying to implement simple jump physics to my player with a character controller and using the unity Physics, but my jump height is slightly inconsistent but all my parameters that interract with the jump are at all times except for the FPS which then assume to be the issue. I can’t really show it clearly cause no videos, but basically that seems to be the issue. My fps limiter is set to 144 but the fps varies wildly.
FPS1
FPS2
FPS3
And the Jump height itself as well.
JumpHeight1
JumpHeight2
JumpHeight3

I tried adding or deleting the FPS limiter, changing the targetFPS, I tried touching to the jump params, I tried changing methods in how I manage the jump, before trying the Physics.gravity method I actually had my own gravity with a velocity calculation that looked like this.
velocity += jumpforce * 3f * gravity when jumping
velocity -= gravity * gravityScaling when airborne
movement.y = velocity * Time.deltaTime at the moment the movement is applied.

I tried to use FixedUpdate instead of Update, or fixedDeltaTime instead of deltaTime… I’m lost. I have no idea how to fix the issue because I don’t know how to touch to how the updates are done based on the FPS more than I already have, and even if I think that’s the only possible issue I see, I’m not even sure the Issue comes from the FPS for sure.

Here is the code of the player when airborne.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAirborne : MonoBehaviour
{

    public void UpdateAirborne(Player player)
    {
        AddMovementWalking(player);
        Accelerate(player);
        Move(player);
    }

    void Move(Player player)
    {
        player.movement.x *= player.speed * Time.deltaTime;
        player.movement += Physics.gravity / 10 * Time.deltaTime;
        player.characterController.Move(player.movement);
    }

    void Accelerate(Player player)
    {
        if (player.playerStates.HasFlag(Player.States.Walking))
        {
            if (player.horizontalJoystickPush * player.movement.x < 0)
            {
                player.speed -= player.acceleration / 2 * Time.deltaTime;
                player.momentumSpeed -= player.acceleration / 2 * Time.deltaTime;
                if (player.speed > player.runningSpeed)
                {
                    player.speed = player.runningSpeed;
                }
            }
            else
            {
                if (player.horizontalJoystickPush != 0)
                {
                    player.speed += player.acceleration * Time.deltaTime;
                    if (player.momentumSpeed < player.runningSpeed)
                    {
                        player.momentumSpeed += player.acceleration * Time.deltaTime;
                        player.momentumDir = player.movement.x;
                    }
                }
                if (player.runningSpeed < player.momentumSpeed)
                {
                    if (player.speed > player.momentumSpeed)
                    {
                        player.speed = player.momentumSpeed;
                    }
                }
                else
                {
                    if (player.speed > player.runningSpeed)
                    {
                        player.speed = player.runningSpeed;
                    }
                }
            }
            if (player.speed < 0)
            {
                player.speed = 0;
            }
        }
    }

    void AddMovementWalking(Player player)
    {
        if (player.speed <= player.momentumSpeed)
        {
            player.movement.x = player.momentumDir;
        }
        else
        {
            player.movement.x = player.horizontalJoystickPush;
        }
    }
}

Here is the code of the player when grounded, and the jump function too.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerGrounded : MonoBehaviour
{
    public void UpdateGrounded(Player player)
    {
        AddMovementWalking(player);
        Accelerate(player);
        Move(player);
        Jump(player);
    }

    void Accelerate(Player player)
    {
        float signAccel = -1;
        if (player.playerStates.HasFlag(Player.States.Walking))
        {
            signAccel = 1;
        }
        player.speed += signAccel * player.acceleration * Time.deltaTime;

        if (player.speed < 0f)
        {
            player.speed = 0f;
        }
        if (Mathf.Abs(player.horizontalJoystickPush) < 0.5f)
        {
            if (player.speed > player.walkingSpeed)
            {
                player.speed = player.walkingSpeed;
            }
        }
        else
        {
            if (player.speed > player.runningSpeed)
            {
                player.speed = player.runningSpeed;
            }
        }
    }

    void AddMovementWalking(Player player)
    {
        if (player.playerStates.HasFlag(Player.States.Walking))
        {
            if (!InputsManager.Instance.controller)
            {
                if (player.playerStates.HasFlag(Player.States.FacingRight))
                {
                    player.horizontalJoystickPush = 1;
                }
                else
                {
                    player.horizontalJoystickPush = -1;
                }
            }
        }
        player.movement.x = player.horizontalJoystickPush;
    }

    void Move(Player player)
    {
        player.momentumSpeed = player.speed;
        player.momentumDir = player.movement.x;
        player.movement.x *= player.speed * Time.deltaTime;
        player.movement.y = -1;
        player.characterController.Move(player.movement);
    }

    void Jump(Player player)
    {
        if (player.playerStates.HasFlag(Player.States.CanJump))
        {
            player.movement.y = player.jumpForce;
            player.playerStates |= Player.States.AirBorne;
            player.playerStates &= ~Player.States.CanJump;
        }
    }
}

And here is the player object: PlayerObject1 PlayerObject2

Unity’s character controller should be updated in Update and the values incremented with Time.deltaTime.

The fps counter in the stats panel has always been useless and you should use your own.

using UnityEngine;
public class FPSIndicator : MonoBehaviour
{
    void OnGUI()
    {
        GUI.Label(new Rect(10, 10, 100, 20), (1/Time.smoothDeltaTime).ToString("f0"));
    }
}

Your character controller seems a little overly complicated and it’s impossible for anybody else to test it because so much functionality is hidden away. If you switch to using the old input system then you’ll be able to post your scripts on the forums and people will be able to test them and give you feedback.

Here’s a very basic character controller:

using UnityEngine;
public class BasicController : MonoBehaviour
{
    public CharacterController cc;
    Vector3 velocity;

    void Start()
    {
        cc = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (cc.isGrounded)
        {
            if (Input.GetButtonDown("Jump")) velocity.y=cc.velocity.y+5;
            else if (velocity.y < 0) velocity.y = -6;
        }
       
        Vector3 force=((transform.right*Input.GetAxis("Horizontal")) + (transform.forward*Input.GetAxis("Vertical")))*10;
        if (Input.GetKey(KeyCode.LeftShift)) force*=2; // run?
        velocity=new Vector3(force.x, velocity.y + Physics.gravity.y * Time.deltaTime, force.z);
        cc.Move(velocity * Time.deltaTime);
    }
}

the main issue is that I’m inexperienced (obviously) and in school actually, and this exercise asks us specifically to use the new input system. Also, the old input system method doesn’t actually work either after testing because the FPS issue still remains with the inconsistent physics influenced by the FPS.

The issue I’m trying to fix or at least explain, is that even when calling upon the Time.deltaTime functions, the physics still end up inconsistent based on FPS when the usage of Time.deltaTime is the exact thing that’s supposed to fix the issue of inconsistent physics based on the FPS.

in terms of missing some of the code, I mean the new input system works well. The inputs are detected correctly when they need to be and the functions are called upon only once and at the right time as well. I don’t really see why the issue would come from this.

And thanks for the advice on the stats panel fps counter, I actually just dodn’t know that it was stupid.

I see from the images you linked that you have a rigidbody present. If that’s on your character controller then you should remove it. The character controller isn’t really part of the physics system and so it doesn’t need a rigidbody.

As for your scripts. They look overly complicated and so they’ll probably be difficult to fix. I think it would be easier for you to find a character controller that somebody has already written and then modify it to meet your requirements. There should be some character controller scripts available that use the new input system.