When sprinting the character goes trough walls

When sprinting the character goes trough walls.

Anyone have a fix?

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
public class PlayerMovementController : MonoBehaviour
{
    [Header("Movement Settings")]
    public float moveSpeed = 5f;
    public float crouchSpeed = 2f;
    public float sprintSpeed = 10f;
    public float jumpForce = 10f;
    public float sprintDuration = 6f;
    public float sprintCooldown = 3f;

    private bool isGrounded;
    private bool isCrouching = false;
    private bool isJumping = false;
    private bool isSprinting = false;
    private bool canSprint = true;

    private Rigidbody rb;
    private CapsuleCollider capsuleCollider;
    private Camera mainCamera;
    private Vector3 originalScale;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        capsuleCollider = GetComponent<CapsuleCollider>();
        rb.interpolation = RigidbodyInterpolation.Interpolate;
        rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
        rb.constraints = RigidbodyConstraints.FreezeRotation;

        mainCamera = Camera.main;
        originalScale = transform.localScale;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.LeftControl) && isGrounded)
        {
            ToggleCrouch();
        }

        if (Input.GetKey(KeyCode.LeftShift) && canSprint && !isSprinting)
        {
            StartCoroutine(Sprint());
        }

        if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
        {
            Jump();
        }

        isJumping = !isGrounded;
    }

    private void FixedUpdate()
    {
        float speed = GetMovementSpeed();
        Vector3 direction = GetMoveDirection();
        float distanceToMove = speed * Time.fixedDeltaTime;

        RaycastHit hit;
        Vector3 nextPosition = rb.position + direction * distanceToMove;

        if (Physics.SphereCast(rb.position, capsuleCollider.radius * 0.9f, direction, out hit, distanceToMove))
        {
            nextPosition = rb.position + direction * hit.distance;

            if (Mathf.Abs(hit.normal.y) < 0.1f)
            {
                Vector3 remainingMovement = Vector3.ProjectOnPlane(direction, hit.normal);
                nextPosition += remainingMovement * (distanceToMove - hit.distance);
            }
        }

        rb.MovePosition(nextPosition);
    }

    public float GetMovementSpeed()
    {
        if (isCrouching)
        {
            return crouchSpeed;
        }
        else if (isSprinting)
        {
            return sprintSpeed;
        }
        else
        {
            return moveSpeed;
        }
    }

    private Vector3 GetMoveDirection()
    {
        Vector3 cameraForward = mainCamera.transform.forward;
        cameraForward.y = 0;
        cameraForward.Normalize();
        Vector3 cameraRight = mainCamera.transform.right;
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector3 moveDirection = (cameraForward * vertical) + (cameraRight * horizontal);
        moveDirection.Normalize();
        return moveDirection;
    }

    private void ToggleCrouch()
    {
        isCrouching = !isCrouching;
        StartCoroutine(CrouchTransition());
    }

    IEnumerator CrouchTransition()
    {
        float targetHeight = isCrouching ? 0.5f : 1f;
        float elapsedTime = 0f;
        float transitionDuration = 0.2f;
        Vector3 initialScale = transform.localScale;

        while (elapsedTime < transitionDuration)
        {
            float t = elapsedTime / transitionDuration;
            transform.localScale = Vector3.Lerp(initialScale, new Vector3(originalScale.x, targetHeight, originalScale.z), t);
            elapsedTime += Time.deltaTime;
            yield return null;
        }

        transform.localScale = new Vector3(originalScale.x, targetHeight, originalScale.z);
    }

    private void Jump()
    {
        if (isGrounded)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            isGrounded = false;
        }
    }

    IEnumerator Sprint()
    {
        isSprinting = true;
        yield return new WaitForSeconds(sprintDuration);
        isSprinting = false;
        canSprint = false;
        yield return new WaitForSeconds(sprintCooldown);
        canSprint = true;
    }

    public bool IsStandingStill()
    {
        return Mathf.Approximately(rb.velocity.magnitude, 0f) && !isJumping;
    }

    public bool IsJumping()
    {
        return isJumping;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }

    private void OnCollisionStay(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }

    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = false;
        }
    }
}

You can try setting the Collision Detection mode to “Continuous” instead of “Discrete” in the Rigidbody component. In Discrete mode, collision is only checked at the final point of the move (which may be beyond the wall). In Continuous mode, collision is checked along the path of motion.

image