Unity Source engine based FPS controller camera leaves collider bounds.

Hello,

I found a really cool character controller. It has the same concept as the source engine does. However, I have an issue that when I move, the camera leaves the bounds of the collider resulting in the player being able to look through the walls. The most I could accomplish is to make the character keep it’s horizontal position like in Wolfenstein3D, however, I want to keep more movement for the player.

Can anyone advise me what values can I edit to prevent the camera from leaving the collider bounds, or at least how could I lock the position of the camera while still letting the player to look around in the collider box bounds?

7584889--940276--upload_2021-10-19_17-46-30.png

using UnityEngine;

public class PlayerAiming : MonoBehaviour
{
    [Header("References")]
    public Transform bodyTransform;

    [Header("Sensitivity")]
    public float sensitivityMultiplier = 1f;
    public float horizontalSensitivity = 1f;
    public float verticalSensitivity   = 1f;

    [Header("Restrictions")]
    public float minYRotation = -90f;
    public float maxYRotation = 90f;

    //The real rotation of the camera without recoil
    private Vector3 real_rotation;

    [Header("Aimpunch")]
    [Tooltip("bigger number makes the response more damped, smaller is less damped, currently the system will overshoot, with larger damping values it won't")]
    public float punchDamping = 9.0f;

    [Tooltip("bigger number increases the speed at which the view corrects")]
    public float punchSpringConstant = 65.0f;

    [HideInInspector]
    public Vector2 punchAngle;

    [HideInInspector]
    public Vector2 punchAngleVel;

    private void Start()
    {
        // Lock the mouse
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible   = false;
    }

    private void Update()
    {
        // Fix pausing
        if (Mathf.Abs(Time.timeScale) <= 0)
            return;

        DecayPunchAngle();

        // Input
        float x_movement = Input.GetAxisRaw("Mouse X") * horizontalSensitivity * sensitivityMultiplier;
        float y_movement = -Input.GetAxisRaw("Mouse Y") * verticalSensitivity  * sensitivityMultiplier;

        // Calculate real rotation from input
        real_rotation   = new Vector3(Mathf.Clamp(real_rotation.x + y_movement, minYRotation, maxYRotation), real_rotation.y + x_movement, real_rotation.z);
        real_rotation.z = Mathf.Lerp(real_rotation.z, 0f, Time.deltaTime * 3f);

        //Apply real rotation to body
        bodyTransform.eulerAngles = Vector3.Scale(real_rotation, new Vector3(0f, 1f, 0f));

        var aim_transform = transform;

        //Apply real rotation to aim
        aim_transform.eulerAngles = real_rotation;

        //Apply recoil
        {
            //If you want the recoil to be purely visual, move it into LateUpdate
            var camera_rotation = aim_transform;

            Vector3 camera_euler_punch_applied = camera_rotation.eulerAngles;
            camera_euler_punch_applied.x += punchAngle.x;
            camera_euler_punch_applied.y += punchAngle.y;

            camera_rotation.eulerAngles = camera_euler_punch_applied;
        }
    }

    public void ViewPunch(Vector2 punch_amount)
    {
        //Remove previous recoil
        punchAngle = Vector2.zero;

        //Recoil go up
        punchAngleVel -= punch_amount * 20;
    }

    private void DecayPunchAngle()
    {
        if (punchAngle.sqrMagnitude > 0.001 || punchAngleVel.sqrMagnitude > 0.001)
        {
            punchAngle += punchAngleVel * Time.deltaTime;
            float damping = 1 - (punchDamping * Time.deltaTime);

            if (damping < 0)
                damping = 0;

            punchAngleVel *= damping;

            float spring_force_magnitude = punchSpringConstant * Time.deltaTime;
            punchAngleVel -= punchAngle * spring_force_magnitude;
        }
        else
        {
            punchAngle    = Vector2.zero;
            punchAngleVel = Vector2.zero;
        }
    }
}

https://github.com/Olezen/UnitySourceMovement

Camera stuff is pretty tricky… it might be best to use Cinemachine from the Unity Package Manager.

If you wanna look at a different FPS controller, here is a pretty full-featured starter prototype FPS based on Character Controller (BasicFPCC):

1 Like

Thank you for sharing.

I’ve got quite attached to the one I’m using myself, however, the one you shared looks interesting. I’ll give it a go.