c# - MovementController Jumping does not seem to work properly - Stack Overflow

I am following a tutorial about unity since i am quite new to unity. The moving and running works as in

I am following a tutorial about unity since i am quite new to unity. The moving and running works as intended however while implementing the jumping it seems to have broken the gravity and not work. It looks like I followed the tutorial properly and can't find my mistake. Below here is the full class.

using UnityEngine;
using UnityEngine.InputSystem;

public class AnimationAndMovementController : MonoBehaviour
{
    private static readonly int IsWalking = Animator.StringToHash("isWalking");
    private static readonly int IsRunning = Animator.StringToHash("isRunning");

    private InputSystem_Actions playerInput;
    private CharacterController characterController;
    private Animator animator;
    private Camera mainCamera;

    private Vector2 currentMovementInput;
    private Vector3 currentMovement;
    private Vector3 currentRunMovement;

    private bool isMovementPressed;
    private bool isRunPressed;
    private float rotationFactorPerFrame = 15.0f;
    private float runMultiplier = 1.8f;
    private float speed = 3.0f;
    private int zero = 0;
    
    private bool isJumpPressed = false;
    private float initialJumpVelocity;
    private float maxJumpHeight = 1.0f;
    private float maxJumpTime = 0.75f;
    private bool isJumping = false;
    
    private float groundedGravity = -.05f;
    private float gravity = -9.8f;

    private void Awake()
    {
        playerInput = new InputSystem_Actions();
        characterController = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
        mainCamera = Camera.main;

        playerInput.Player.Move.started += OnMovementInput;
        playerInput.Player.Move.canceled += OnMovementInput;
        playerInput.Player.Move.performed += OnMovementInput;

        playerInput.Player.Sprint.started += OnRun;
        playerInput.Player.Sprint.canceled += OnRun;

        playerInput.Player.Jump.started += OnJump;
        playerInput.Player.Jump.canceled += OnJump;

        SetupJumpVariables();
    }
    
    private void SetupJumpVariables()
    {
        float timeToApex = maxJumpTime / 2;
        gravity = (-2 * maxJumpHeight) / Mathf.Pow(timeToApex, 2);
        initialJumpVelocity = (2 * maxJumpHeight) / timeToApex;
    }
    
    private void HandleJump()
    {
        if (characterController.isGrounded && isJumpPressed && !isJumping)
        {
            isJumping = true;
            currentMovement.y = initialJumpVelocity * .5f;
            currentRunMovement.y = initialJumpVelocity *.5f;
        }
        else if (isJumping && !isJumpPressed && characterController.isGrounded)
        {
            isJumping = false;
        }
    }
    
    private void OnJump(InputAction.CallbackContext context)
    {
        isJumpPressed = context.ReadValueAsButton();
    }

    private void OnRun(InputAction.CallbackContext context)
    {
        isRunPressed = context.ReadValueAsButton();
    }

    private void OnMovementInput(InputAction.CallbackContext context)
    {
        currentMovementInput = context.ReadValue<Vector2>();
        isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
    }

    private void UpdateMovement()
    {
        Vector3 forward = mainCamera.transform.forward;
        Vector3 right = mainCamera.transform.right;

        forward.y = 0f;
        right.y = 0f;

        forward.Normalize();
        right.Normalize();

        currentMovement = forward * currentMovementInput.y + right * currentMovementInput.x;
        currentRunMovement = currentMovement * runMultiplier;
    }

    private void HandleRotation()
    {
        Vector3 positionToLookAt;
        positionToLookAt.x = currentMovement.x;
        positionToLookAt.y = zero;
        positionToLookAt.z = currentMovement.z;

        Quaternion currentRotation = transform.rotation;

        if (isMovementPressed)
        {
            Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
            transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
        }
    }

    private void HandleGravity()
    {
        bool isFalling = currentMovement.y < 0.0f || !isJumpPressed;
        float fallMultiplier = 2.0f;
        
        if (characterController.isGrounded)
        {
            currentMovement.y = groundedGravity;
            currentRunMovement.y = groundedGravity;
        }
        else if (isFalling)
        {
            float previousY = currentMovement.y;
            float newY = currentMovement.y + (gravity * fallMultiplier * Time.deltaTime);
            float nextY = Mathf.Max((previousY + newY) * .5f, -20f);
            currentMovement.y += nextY;
        }
        else
        {
            float previousY = currentMovement.y;
            float newY = currentMovement.y + gravity * Time.deltaTime;
            float nextY = (previousY + newY) * .5f;
            currentMovement.y += nextY;
            currentRunMovement.y += nextY;
        }
    }

    private void HandleAnimation()
    {
        bool isWalking = animator.GetBool(IsWalking);
        bool isRunning = animator.GetBool(IsRunning);

        if (isMovementPressed && !isWalking)
        {
            animator.SetBool(IsWalking, true);
        }
        else if (!isMovementPressed && isWalking)
        {
            animator.SetBool(IsWalking, false);
        }

        if ((isMovementPressed && isRunPressed) && !isRunning)
        {
            animator.SetBool(IsRunning, true);
        }
        else if ((!isMovementPressed || !isRunPressed) && isRunning)
        {
            animator.SetBool(IsRunning, false);
        }
    }

    private void Update()
    {
        UpdateMovement();
        HandleAnimation();
        HandleRotation();

        if (isRunPressed)
        {
            characterController.Move(currentRunMovement * (speed * Time.deltaTime));
        }
        else
        {
            characterController.Move(currentMovement * (speed * Time.deltaTime));
        }
        
        HandleGravity();
        HandleJump();
    }

    private void OnEnable()
    {
        playerInput.Player.Enable();
    }

    private void OnDisable()
    {
        playerInput.Player.Disable();
    }
}

In this gif i showcase the issue, the player is supposed to stay on the ground using the gravity, also even when i walk off the ground the player does not go down. In the moments that i am standing still i am pressing space mulitple times trying to jump, as you can see nothing happens. (the only part i strayed from the tutorial itself is i implemented camera based movement)

Hope someone can find my issue Here is the tutorial for reference: ;list=PLwyUzJb_FNeQrIxCEjj5AMPwawsw5beAy&index=4

I am following a tutorial about unity since i am quite new to unity. The moving and running works as intended however while implementing the jumping it seems to have broken the gravity and not work. It looks like I followed the tutorial properly and can't find my mistake. Below here is the full class.

using UnityEngine;
using UnityEngine.InputSystem;

public class AnimationAndMovementController : MonoBehaviour
{
    private static readonly int IsWalking = Animator.StringToHash("isWalking");
    private static readonly int IsRunning = Animator.StringToHash("isRunning");

    private InputSystem_Actions playerInput;
    private CharacterController characterController;
    private Animator animator;
    private Camera mainCamera;

    private Vector2 currentMovementInput;
    private Vector3 currentMovement;
    private Vector3 currentRunMovement;

    private bool isMovementPressed;
    private bool isRunPressed;
    private float rotationFactorPerFrame = 15.0f;
    private float runMultiplier = 1.8f;
    private float speed = 3.0f;
    private int zero = 0;
    
    private bool isJumpPressed = false;
    private float initialJumpVelocity;
    private float maxJumpHeight = 1.0f;
    private float maxJumpTime = 0.75f;
    private bool isJumping = false;
    
    private float groundedGravity = -.05f;
    private float gravity = -9.8f;

    private void Awake()
    {
        playerInput = new InputSystem_Actions();
        characterController = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
        mainCamera = Camera.main;

        playerInput.Player.Move.started += OnMovementInput;
        playerInput.Player.Move.canceled += OnMovementInput;
        playerInput.Player.Move.performed += OnMovementInput;

        playerInput.Player.Sprint.started += OnRun;
        playerInput.Player.Sprint.canceled += OnRun;

        playerInput.Player.Jump.started += OnJump;
        playerInput.Player.Jump.canceled += OnJump;

        SetupJumpVariables();
    }
    
    private void SetupJumpVariables()
    {
        float timeToApex = maxJumpTime / 2;
        gravity = (-2 * maxJumpHeight) / Mathf.Pow(timeToApex, 2);
        initialJumpVelocity = (2 * maxJumpHeight) / timeToApex;
    }
    
    private void HandleJump()
    {
        if (characterController.isGrounded && isJumpPressed && !isJumping)
        {
            isJumping = true;
            currentMovement.y = initialJumpVelocity * .5f;
            currentRunMovement.y = initialJumpVelocity *.5f;
        }
        else if (isJumping && !isJumpPressed && characterController.isGrounded)
        {
            isJumping = false;
        }
    }
    
    private void OnJump(InputAction.CallbackContext context)
    {
        isJumpPressed = context.ReadValueAsButton();
    }

    private void OnRun(InputAction.CallbackContext context)
    {
        isRunPressed = context.ReadValueAsButton();
    }

    private void OnMovementInput(InputAction.CallbackContext context)
    {
        currentMovementInput = context.ReadValue<Vector2>();
        isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
    }

    private void UpdateMovement()
    {
        Vector3 forward = mainCamera.transform.forward;
        Vector3 right = mainCamera.transform.right;

        forward.y = 0f;
        right.y = 0f;

        forward.Normalize();
        right.Normalize();

        currentMovement = forward * currentMovementInput.y + right * currentMovementInput.x;
        currentRunMovement = currentMovement * runMultiplier;
    }

    private void HandleRotation()
    {
        Vector3 positionToLookAt;
        positionToLookAt.x = currentMovement.x;
        positionToLookAt.y = zero;
        positionToLookAt.z = currentMovement.z;

        Quaternion currentRotation = transform.rotation;

        if (isMovementPressed)
        {
            Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
            transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime);
        }
    }

    private void HandleGravity()
    {
        bool isFalling = currentMovement.y < 0.0f || !isJumpPressed;
        float fallMultiplier = 2.0f;
        
        if (characterController.isGrounded)
        {
            currentMovement.y = groundedGravity;
            currentRunMovement.y = groundedGravity;
        }
        else if (isFalling)
        {
            float previousY = currentMovement.y;
            float newY = currentMovement.y + (gravity * fallMultiplier * Time.deltaTime);
            float nextY = Mathf.Max((previousY + newY) * .5f, -20f);
            currentMovement.y += nextY;
        }
        else
        {
            float previousY = currentMovement.y;
            float newY = currentMovement.y + gravity * Time.deltaTime;
            float nextY = (previousY + newY) * .5f;
            currentMovement.y += nextY;
            currentRunMovement.y += nextY;
        }
    }

    private void HandleAnimation()
    {
        bool isWalking = animator.GetBool(IsWalking);
        bool isRunning = animator.GetBool(IsRunning);

        if (isMovementPressed && !isWalking)
        {
            animator.SetBool(IsWalking, true);
        }
        else if (!isMovementPressed && isWalking)
        {
            animator.SetBool(IsWalking, false);
        }

        if ((isMovementPressed && isRunPressed) && !isRunning)
        {
            animator.SetBool(IsRunning, true);
        }
        else if ((!isMovementPressed || !isRunPressed) && isRunning)
        {
            animator.SetBool(IsRunning, false);
        }
    }

    private void Update()
    {
        UpdateMovement();
        HandleAnimation();
        HandleRotation();

        if (isRunPressed)
        {
            characterController.Move(currentRunMovement * (speed * Time.deltaTime));
        }
        else
        {
            characterController.Move(currentMovement * (speed * Time.deltaTime));
        }
        
        HandleGravity();
        HandleJump();
    }

    private void OnEnable()
    {
        playerInput.Player.Enable();
    }

    private void OnDisable()
    {
        playerInput.Player.Disable();
    }
}

In this gif i showcase the issue, the player is supposed to stay on the ground using the gravity, also even when i walk off the ground the player does not go down. In the moments that i am standing still i am pressing space mulitple times trying to jump, as you can see nothing happens. (the only part i strayed from the tutorial itself is i implemented camera based movement)

Hope someone can find my issue Here is the tutorial for reference: https://www.youtube/watch?v=h2r3_KjChf4&list=PLwyUzJb_FNeQrIxCEjj5AMPwawsw5beAy&index=4

Share Improve this question asked Jan 17 at 17:37 DeagarysDeagarys 1018 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I'm going to answer exactly you ask. Your code is quite overloaded separate animations from movement logic. It's not necessary to handle gravity values. The cause of static gravity you didn't add RigidBody component to your gameobject. I've overwriten some code area for properly work.

//Jump force
private Vector3 _jumpVelocity;
//It using for controlling object moving by physics
private RigidBody _rb;

private void Awake()
{
    //Get RigidBody component from this object
    _rb = GetComponents<RigidBody>();
    //
    //Your code realisation
    //
    SetupJumpVariables();
}

private void SetupJumpVariables()
{
    //You shouldn't calculate the gravity value. It set 9.8 as default
    float timeToApex = maxJumpTime / 2;
    //There's a way to stay at float field. But it more comfortable i think
    initialJumpVelocity = new Vector3(0, 2 * maxJumpHeight / timeToApex);
}

private void HandleJump()
{
    if (characterController.isGrounded && isJumpPressed && !isJumping)
    {
        isJumping = true;
        //RigidBody add force to jump by physics
        _rb.AddForce(_jumpVelocity, ForceMode.Impulse);
    }
    else if (isJumping && !isJumpPressed && characterController.isGrounded)
    {
        isJumping = false;
    }
}

The code is not full. Remove all gravity handling code because of unnecessary.

As for not related to question points. Moving logic is not correct at all. It work by Update. That's the common mistake of beginers. Use FixedUpdate instead otherwise it will cause physics issue you wouldn't expect. Don't use 2 fields for move logic: currentMovement currentRunMovement. Use them as float speed values instead of dynamic moving fields.

//Recreated 2 Vector3 fields to float fields
private float _runSpeed;
private float _walkSpeed;
private float _currentSpeed;

private void FixedUpdate()
{
    //Movement has moved from Update to this method
    UpdateMovement();
}

private void Update()
{
    //Your code
    //If else construction define current speed instead of movement
    if (isRunPressed)
    {
        _currentSpeed = _runSpeed
    }
    else
    {
        _currentSpeed = _walkSpeed
    }
}

private void UpdateMovement()
{
    Vector3 forward = mainCamera.transform.forward;
    Vector3 right = mainCamera.transform.right;

    forward.y = 0f;
    right.y = 0f;

    forward.Normalize();
    right.Normalize();

    //Get direction without speed handling
    currentMovement = forward * currentMovementInput.y + right * currentMovementInput.x;

     //Move logic character has moved from Update to this method
     characterController.Move(currentRunMovement * (_currentSpeed * Time.fixedDeltaTime));
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745351812a4623877.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信