Help with Collision Detection

I’m new to scripting (even though I’ve posted that same thing ages ago, I haven’t been studying as adamantly as I should have been) and working on a small 3D game. With the idea I have, I didn’t want to use a rigidbody for the character and the character controller has issues with detecting collisions (by the way, if there’s a fix for that – having the character be jolted away from the other collider upon impact – I’m all ears).

So, I’ve been working on my own movement system, but have an issue with part of the character collider going into the other collider. Sometimes, it just passes through completely. I’d love to learn a fix for this or a different way to detect collisions.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [Header("Movement Variables")]
    public float speed = 6f;
    public float jumpSpeed = 8f;
    public float rotationSpeed = 180f;
    public bool smooth;
    public float smoothSpeed;

    [Header("Physics Variables")]
    public LayerMask discludePlayer;
    public float sphereCastRadius = 0.17f;
    public float sphereCastMaxDistance = 20f;
    public float overlapSphereRadius = 0.57f;
    public float raycastMaxDistance = 3.1f;
    public float gravity = 9.81f;

    public float playerHeight = 2f;

    private Vector3 move = Vector3.zero;
    [SerializeField] private Vector3 _liftPoint = new Vector3(0f, 1.2f, 0f);
    [SerializeField] private Vector3 _groundCheckPoint = new Vector3(0f, -0.87f, 0f);
    private RaycastHit _groundHit;
    private bool _isGrounded;
    private bool _inputJump;
    private CapsuleCollider _capsuleCol;
    private Vector3 _velocity;
    private Vector3 _vel;


    void Start()
    {
        _capsuleCol = GetComponent<CapsuleCollider>();
    }


    void Update()
    {
        Movement();
        GroundChecking();
        CollisionChecking();
    }

    private void Movement()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        float currentH = 0f;
        float currentV = 0f;
       
        currentH = Mathf.Lerp(currentH, h, speed);
        currentV = Mathf.Lerp(currentV, v, speed);
        move = new Vector3(currentH, 0f, currentV);

        transform.position += move * Time.deltaTime;

        Transform camera = Camera.main.transform;
        Vector3 direction;

        direction = camera.right * currentH + camera.forward * currentV;

        float directionLength = direction.magnitude;

        direction.y = 0f;
        direction = direction.normalized * directionLength;

        Vector3 currentDirection = Vector3.zero;

        if(direction != Vector3.zero)
        {
            currentDirection = Vector3.Slerp(currentDirection, direction, rotationSpeed * Time.deltaTime);
            transform.rotation = Quaternion.LookRotation(currentDirection);
        }

        transform.position += currentDirection * speed * Time.deltaTime;
        _velocity += transform.position;
        _vel = _velocity * speed;
        _vel = transform.TransformDirection(_vel);
        _velocity = Vector3.zero;
       
    }

    private void GroundChecking()
    {
        Ray ray = new Ray(transform.TransformPoint(_liftPoint), Vector3.down);
        RaycastHit tempHit = new RaycastHit();

        if (Physics.SphereCast(ray, sphereCastRadius, out tempHit, sphereCastMaxDistance, discludePlayer))
            GroundConfirm(tempHit);
        else
            _isGrounded = false;
    }

    private void GroundConfirm(RaycastHit tempHit)
    {
        Collider[] col = new Collider[3];
        int num = Physics.OverlapSphereNonAlloc(transform.TransformPoint(_groundCheckPoint), overlapSphereRadius, col, discludePlayer);

        //_isGrounded = false;

        for (int i = 0; i < num; i++)
        {
            if(col[i].transform == tempHit.transform)
            {
                _groundHit = tempHit;
                _isGrounded = true;

                if(_inputJump == false)
                {
                    Vector3 smoothing = new Vector3(transform.position.x, (_groundHit.point.y + playerHeight / 2), transform.position.z);

                    if (!smooth)                   
                        transform.position = smoothing;                   
                    else
                        transform.position = Vector3.Lerp(transform.position, smoothing, smoothSpeed * Time.deltaTime);
                }
                break;
            }
        }

        if(num <= 1 && tempHit.distance <= raycastMaxDistance && _inputJump == false)
        {
            if(col[0] != null)
            {
                Ray ray = new Ray(transform.TransformPoint(_liftPoint), Vector3.down);
                RaycastHit hit;

                if (Physics.Raycast(ray, out hit, raycastMaxDistance, discludePlayer))
                {
                    if(hit.transform != col[0].transform)
                    {
                        _isGrounded = false;
                        return;
                    }
                }
            }
        }
    }

    public void CollisionChecking()
    {
        Vector3 point0 = transform.position + new Vector3(transform.position.x, transform.position.y + 1, transform.position.z);
        Vector3 point1 = transform.position + new Vector3(transform.position.x, transform.position.y - 1, transform.position.z);
        Collider[] overlaps = new Collider[4];
        int num = Physics.OverlapCapsuleNonAlloc(point0, point1, _capsuleCol.radius, overlaps, discludePlayer, QueryTriggerInteraction.UseGlobal);

        for(int i = 0; i < num; i++)
        {
            Transform t = overlaps[i].transform;

            if(Physics.ComputePenetration(_capsuleCol, transform.position, transform.rotation, overlaps[i], t.position, t.rotation, out Vector3 dir, out float dist))
            {
                Vector3 penetrationVector = dir * dist;
                Vector3 velocityProjected = Vector3.Project(_velocity, -dir);

                transform.position += penetrationVector;
                _vel -= velocityProjected;
            }
        }
}

The reason I’m doing it this way is that I wrote a similar script where collision detecting worked, but I couldn’t get the character to rotate in the direction it was heading. The main difference was:

Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));

After changing that so my character could turn, the math behind velocityProjected fell apart. Again, I’m happy with a fix for this or a simpler way to do detect collisions.

Fixed it! I moved line 79 into the if statement directly above it and removed transform.position from lines 146 and 147.