'How to jump properly using character controller?

I'm using a character controller for my player movement. I had walking and running working, but I couldn't get the jumping to work.

Here is my code:

[SerializeField] Transform playerCamera = null;
[SerializeField] float mouseSensitivity = 3.5f;
[SerializeField] float walkSpeed = 10.0f;
[SerializeField] float RunSpeed = 12.0f;
[SerializeField] float gravity = 9.81f;
[SerializeField] bool lockCursor = true;
[SerializeField] [Range(0.0f, 0.5f)] float moveSmoothTime = 0.3f;
[SerializeField] [Range(0.0f, 0.5f)] float mouseSmoothTime = 0.03f;
public float jumpHeight = 3f;

Vector3 velocity;
public float verticalVelocity;
float cameraPitch = 0.0f;
float VelocityY = 0.0f;
CharacterController controller = null;

Vector2 currentDir = Vector2.zero;
Vector2 currentDirVelocity = Vector2.zero;

Vector2 currentMouseDelta = Vector2.zero;
Vector2 currentMouseDeltaVelocity = Vector2.zero;

void Start()
{
    controller = GetComponent<CharacterController>();
    if (lockCursor)
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }
}
void Update()
{
    UpdateMouseLook();
    UpdateMovement();
}
void UpdateMouseLook()
{
    Vector2 targetMouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));

    currentMouseDelta = Vector2.SmoothDamp(currentMouseDelta, targetMouseDelta, ref currentMouseDeltaVelocity, mouseSmoothTime);

    cameraPitch -= currentMouseDelta.y * mouseSensitivity;

    cameraPitch = Mathf.Clamp(cameraPitch, -90.0f, 90.0f);

    playerCamera.localEulerAngles = Vector3.right * cameraPitch;

    transform.Rotate(Vector3.up * currentMouseDelta.x * mouseSensitivity);
}
void UpdateMovement()
{
    Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
    targetDir.Normalize();

    currentDir = Vector2.SmoothDamp(currentDir, targetDir, ref currentDirVelocity, moveSmoothTime);

    if (controller.isGrounded)
        VelocityY = 0.0f;

    VelocityY += gravity * Time.deltaTime;

    velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * walkSpeed + Vector3.up * VelocityY;

    controller.Move(velocity * Time.deltaTime);

    if ((Input.GetKey("left shift") || Input.GetKey("right shift")) && controller.isGrounded && !Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.DownArrow))
    {
        velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * RunSpeed + Vector3.up * VelocityY;

        controller.Move(velocity * Time.deltaTime);
    }

    if (Input.GetKeyDown(KeyCode.J) && controller.isGrounded)
    {

        Debug.Log("Now Jumping!!");
        VelocityY = Mathf.Sqrt(jumpHeight * -2f * gravity);
       
    }
}

Note: I'm not using rigidbody on my character.

The jumping is not working every time, on some clicks, it jumps and on most of the clicks nothing happens even Debug.Log("Now Jumping!!"); is not getting printed every time I hit J. How can I fix this?



Solution 1:[1]

I solved this problem. You have no choice but to add physics to the character controller. This is a simple code that has the same feature, but you should coordinate the movement and jump.

public class Player : MonoBehaviour
{
    private Vector3 playerVelocity;
    private CharacterController _controller;

    public float jumpPower = 1f; // 1 is ok for -9.8 gravity
    void Start()
    {
        _controller = GetComponent<CharacterController>();
    }
    void Update()
    {
        playerVelocity += Physics.gravity * Time.deltaTime;

        _controller.Move(playerVelocity);

        if (_controller.isGrounded)
        {
            playerVelocity.y = Input.GetKeyDown(KeyCode.Space) ? jumpPower : 0;
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 KiynL