Home > Mobile >  How to fix Character Controller jumping up steep slopes?
How to fix Character Controller jumping up steep slopes?

Time:07-29

I'm using a 3d character controller for my player but I can't figure out how to stop it from being able to jump up steep slopes. I've looked around and could only find one video that fixes the issue but after the character slides down the slope it stays locked in the slide movement function and I'm not really sure why. I've edited out the code that doesn't matter for clarity, pls lmk if u know how to fix this!

Heres the code:

 public class PlayerMovement : MonoBehaviour
 {
     public CharacterController controller;
 
     public float speed = 12f;
     public float gravity = -9.81f;
     public float jumpHeight = 3f;
 
     public Transform groundCheck;
     public float groundDistance = 0.4f;
     public LayerMask groundMask;
 
     //SLOPES
     private float groundRayDistance = 1;
     private RaycastHit slopeHit;
     public float slopeSlideSpeed;
 
     Vector3 velocity;
     bool isGrounded;
 
         
     // Update is called once per frame
     void Update()
     {
         HandleMovement();
         HandleAnimations(); 
 
         if(OnSteepSlope())
         {
             SteepSlopeMovement();
         }
     }
 
 
 
      private void HandleMovement()
     {
         isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
 
         if (isGrounded && velocity.y < 0)
         {
             velocity.y = -2f;
         }
 
 
         float x = Input.GetAxis("Horizontal");
         float z = Input.GetAxis("Vertical");
 
         move = transform.right * x   transform.forward * z;
 
         controller.Move(move * speed * Time.deltaTime);
 
         if (Input.GetButtonDown("Jump") && isGrounded)
         {
             velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
         }
 
         velocity = AdjustVelocityToSlope(velocity);
         velocity.y  = gravity * Time.deltaTime;
 
         controller.Move(velocity * Time.deltaTime);
     }
 
     private Vector3 AdjustVelocityToSlope(Vector3 velocity)
     {
         var ray = new Ray(transform.position, Vector3.down);
 
         if(Physics.Raycast(ray, out RaycastHit hitInfo, 0.2f))
         {
             var slopeRotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
             var adjustedVelocity = slopeRotation * velocity;
 
             if(adjustedVelocity.y < 0)
             {
                 return adjustedVelocity;
             }
         }
 
         return velocity;
 
     }
 
     private bool OnSteepSlope()
     {
         if (!isGrounded) return false;
 
         if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, (controller.height / 2)   groundRayDistance))
         {
             float slopeAngle = Vector3.Angle(slopeHit.normal, Vector3.up);
             if (slopeAngle > controller.slopeLimit) return true;
         }
         return false;
     }
 
     private void SteepSlopeMovement()
     {
         Vector3 slopeDirection = Vector3.up - slopeHit.normal * Vector3.Dot(Vector3.up, slopeHit.normal);
         float slideSpeed = speed   slopeSlideSpeed   Time.deltaTime;
 
         velocity = slopeDirection * -slideSpeed;
         velocity.y = velocity.y - slopeHit.point.y;
     }

CodePudding user response:

I see you've got dot product check inside of SteepSlopeMovement might be useful to draw some rays with gizmos of the player's down and the normal of the surface. Then you can adjust the threshold value for when you can jump.

CodePudding user response:

OnSteepSlope() wasnt returning false so I put the return false statement in an else loop, I also changed how I was moving the character in SteepSlopeMovement by using controller.Move() instead of directly changing the velocity. It works great now

  • Related