Adding FPS Sliding using the Character Controller

97 Views Asked by At

I'm currently working on a FPS "Speedrun" game & I want to add "Sliding" to the players movement. I already added "Crouching", but currently I'm stuck at getting the sliding done. (I'm using the Character Controller) I've tried many things, but nothing really worked. Heres the current PlayerMovement script:

using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.EventSystems;
 using UnityEngine.UIElements;
 
 public class PlayerMovement : MonoBehaviour
 {
     public CharacterController controller;
     private Rigidbody rb;
     public Transform cameraTransform;
 
     public HeadBobController headBobController;
 
     [Header("Movement")]
     private float speedMultiplier = 1f;
     public float speed = 12f;
     public float sprintSpeed = 20f;
     public float slopeSpeed = 0.01f;
 
     public float gravity = -9.81f;
     public float jumpHeight = 3f;
     public float sensitivity = 2f;
     public float cameraRotationLimit = 85f;
 
     [Header("Countermovement")]
     public float counterMovement = 0.175f;
     private float threshold = 0.01f;
     public float maxSlopeAngle = 35f;
 
     [Header("Sliding / Crouch")]
     public float slideSpeed;
     float originalHeight;
     public float reducedHeight;
     float targetHeight = 2f;
     public float timeToCrouch = 0.25f;
     float timeElapsed = 0;
 
     bool canStopCrouching;
     bool wantStopCrouch;
 
     bool isRunning = false;
     public bool isCrouching = false;
     bool canUseHeadbob = true;
     bool WillSlideOnSlopes = true;
 
     bool IsSliding
     {
         get
         {
             if (controller.isGrounded && Physics.Raycast(transform.position, Vector3.down, out RaycastHit slopeHit, 3f))
             {
                 hitPointNormal = slopeHit.normal;
                 return Vector3.Angle(hitPointNormal, Vector3.up) > controller.slopeLimit;
 
             } else
             {
                 return false;
             }
         }
     }
 
     [Header("Headbob")]
     [SerializeField] private float walkBobSpeed = 14f;
     [SerializeField] private float walkBobAmount = 0.05f;
     [SerializeField] private float sprintBobSpeed = 18f;
     [SerializeField] private float sprintBobAmount = 0.11f;
     [SerializeField] private float crouchBobSpeed = 8f;
     [SerializeField] private float crouchBobAmount = 0.025f;
     private float defaultYPos = 0;
     private float timer;
 
     private Vector3 hitPointNormal;
 
     [Header("Ground Check")]
     public Transform groundCheck;
     public float groundDistance = 0.4f;
     public LayerMask groundMask;
 
     Vector3 velocity;
     public bool isGrounded;
 
     [Header("Camera")]
     float cameraRotationX = 0f;
     float cameraRotationY = 0f;
 
     public Camera camera;
     public Transform orientation;
 
     [Header("Other")]
     public GameObject speedlines;
     public ParticleSystem jumpParticle;
 
     void Start()
     {
         rb = GetComponent<Rigidbody>();
         controller = GetComponent<CharacterController>();
         originalHeight = controller.height;
         defaultYPos = camera.transform.localPosition.y;
         //Cursor.lockState = CursorLockMode.Locked;
         //Cursor.visible = false;
     }
 
     public void Update()
     {
         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");
 
         Vector3 move = transform.right * x + transform.forward * z;
         move = Vector3.ClampMagnitude(move, 1f);
 
         if (Input.GetKey(KeyCode.LeftShift) && !isCrouching)
         {
             controller.Move(move * sprintSpeed * Time.deltaTime);
             isRunning = true;
             headBobController.amplitude = 0.1f;
             headBobController.frequency = 30f;
         } else
         {
             controller.Move(move * speed * speedMultiplier * Time.deltaTime);
             isRunning = false;
             headBobController.amplitude = 0.0426f;
             headBobController.frequency = 19.1f;
         }
 
         if (Physics.Raycast(camera.transform.position, Vector3.up, 1f))
         {
             canStopCrouching = false;
         } else
         {
             canStopCrouching = true;
         }
 
         if (canStopCrouching && wantStopCrouch && !Physics.Raycast(camera.transform.position, Vector3.up, 1f))
         {
             wantStopCrouch = false;
             StopCrouch();
         }
 
         if (Input.GetKeyDown(KeyCode.LeftControl) && isGrounded)
         {
             //controller.height = Mathf.Lerp(reducedHeight, originalHeight, timeElapsed);
             StartCrouch();
         } else if(Input.GetKeyUp(KeyCode.LeftControl) && isGrounded && !Physics.Raycast(camera.transform.position, Vector3.up, 1f))
         {
             //controller.height = Mathf.Lerp(originalHeight, targetHeight, timeElapsed);
             StopCrouch();
         } else if(Input.GetKeyUp(KeyCode.LeftControl) && isGrounded && Physics.Raycast(camera.transform.position, Vector3.up, 1f))
         {
             wantStopCrouch = true;
         }
 
         if (Input.GetKey(KeyCode.LeftControl) && isRunning && isGrounded)
         {
             //Sliding
         }
 
         if (canUseHeadbob && isGrounded)
         {
             if (Mathf.Abs(move.x) > 0.1f || Mathf.Abs(move.z) > 0.1f)
             {
                 timer += Time.deltaTime * (isCrouching ? crouchBobSpeed : isRunning ? sprintBobSpeed : walkBobSpeed);
                 camera.transform.localPosition = new Vector3(camera.transform.localPosition.x, defaultYPos + Mathf.Sin(timer) * (isRunning ? sprintBobAmount : walkBobAmount), camera.transform.localPosition.z);
             }
         }
         
         if(WillSlideOnSlopes && IsSliding)
         {
             move += new Vector3(hitPointNormal.x, -hitPointNormal.y, hitPointNormal.z) * slopeSpeed;
         }
 
         if (isRunning)
         {
             speedlines.active = true;
         } else {
             speedlines.active = false;
         }
 
         controller.Move(move * speed * speedMultiplier * Time.deltaTime);
 
         if (Input.GetButtonDown("Jump") && isGrounded)
         {
             controller.Move(-transform.forward * 0.1f);
             velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
             jumpParticle.Play();
         }
 
         velocity.y += gravity * Time.deltaTime;
 
         controller.Move(velocity * Time.deltaTime);
 
         // Rotate the player based on mouse input
         float mouseX = Input.GetAxis("Mouse X") * sensitivity;
         float mouseY = Input.GetAxis("Mouse Y") * sensitivity;
 
         cameraRotationY += mouseX;
 
         cameraRotationX -= mouseY;
         cameraRotationX = Mathf.Clamp(cameraRotationX, -cameraRotationLimit, cameraRotationLimit);
 
         cameraTransform.localEulerAngles = new Vector3(cameraRotationX, cameraRotationY, 0f);
         transform.eulerAngles = new Vector3(0f, cameraRotationY, 0f);
     }
 
     private void StartCrouch()
     {
         controller.height = reducedHeight;
         speedMultiplier = 0.5f;
         isCrouching = true;
     }
 
     private void StopCrouch()
     {
         controller.height = originalHeight;
         speedMultiplier = 1f;
         isCrouching = false;
     }
 }

It would be very nice if anyone could try to explain me how to implement it into this code using the Character Controller! :)

I've tried multiple Youtube Tutorial solutions & a lot in Online Forums, nothing really worked for me for some reason. Often the system wouldn't even work (nothing happened). I want the player to have the crouching ability (which is implemented) & to slide when isRunning & when the player isGrounded

0

There are 0 best solutions below