Help me with my camera controller?

so I Created a basic camera controller and a floor to walk around on, I added coliders to the camera and to the floor, and have a gravity function to pull the camera down to the floor.

I am successfully capturing WASD commands and moving the camera based on that,

I am also successfully capturing mouse movement and panning the camera based on that.

The issue i’m encountering is, when my camera is angled towards the floor, and I hold W then my camera will move in a striaght line in the direction its facing through the floor.

The other issue i’m encountering is I need to add a maximum rotation value to my camera, becuase if the user rotates it upside down then the gravity function is no longer true, and it falls into the sky.

here is my camera controller code:

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

public class CameraController : MonoBehaviour
{
    public float moveSpeed = 5.0f;
    public float rotationSpeed = 2000.0f;
     public float gravity = 9.81f;  // Gravity force
        public float groundCheckDistance = 2f;
           private float verticalVelocity = 0.0f;  // Gravity's vertical effect
            private bool isGrounded;
             public LayerMask groundLayer;


            void ApplyGravity()
                    {
                        // Check if the camera is grounded
                       
                        isGrounded = Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), groundCheckDistance, groundLayer);

                        if (isGrounded)
                        {
                            verticalVelocity = 0;  // Reset gravity when on the ground
                        }
                        else
                        {
                            // Apply gravity when not grounded
                            verticalVelocity -= gravity * Time.deltaTime;
                        }

                        // Move the camera down based on gravity
                        transform.Translate(Vector3.up * verticalVelocity * Time.deltaTime);
                    }

    void Update()
    {
     Camera camera = GetComponent<Camera>();
        // Handle movement with WASD
        if(isGrounded){


            // Handle movement with WASD
            float moveX = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime; // A/D or left/right arrow
            float moveZ = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime; // W/S or up/down arrow

            // Create a global movement vector
            Vector3 move = new Vector3(moveX, 0, moveZ);

            // Move the camera globally
            camera.transform.Translate(move);
        }

        ApplyGravity();

        float rotationX = Input.GetAxis("Mouse X") * rotationSpeed * Time.deltaTime;
        float rotationY = -Input.GetAxis("Mouse Y") * rotationSpeed * Time.deltaTime;

        // Rotate around the global Y axis
        camera.transform.Rotate(0, rotationX, 0, Space.World);
        // Rotate around the local X axis (for looking up/down)

        camera.transform.Rotate(rotationY, 0, 0);



        if (Input.GetKeyDown(KeyCode.Space)){

            }

    }



    }


here is a screen shot of how i have attached the collider to the camera:

here is a screen shot how how i have configured the collider for the floor:

Many thanks in advance

You’re directly modifying the transform which will bypass all physics. If you want movement that respects physics, you will need to use a rigidbody and make sure all movement is done via the rigidbody API.

That said you’re mixing up two different things here. Your camera controller is also a character controller. Ideally these two things should be handled separately in two separate components. The character controller moves the character, and the camera controller comes along for the ride, and only needs to handle rotation rather than movement.

THAT SAID, Unity has a built in package that can handle camera stuff for you: Cinemachine

You can get a first person camera working out of the box and can focus on the fun stuff instead. Camera stuff does hit intermediate to advanced stuff quite quickly, as you begin dealing with rotations.

1 Like

Ok thanks for the input, I have changed to the method you suggested ( or atleast i think i have)

I added a 3d capsule to the scene and attached a “character controller” to it

I have taken a new camera object and set it inside the top of the the capsule

I believe what your saying regarding the code for the controller is i need to scrap it and call the rigidbodyAPI.

give me a bit and I will rewrite it for the character controller calling that api.

but question, When I attach the new script to the capsule, how do i get the camera to move along with it?

ok so i have updated it and i’m encountering a different issue now

So i’ve removed the scripting logic entirely and attached a rigidbody to the capsule, I have the ground element marked as “ground layer”

but when i press play my capsule falls through the floor:


capsule^


ground layer ^

You don’t have a collider on your capsule.

Also, I see you have both a character controller component that you weren’t using in both screenshots. A rigidbody and a character controller component don’t play well together. Use one or the other.

oh ok, forgive my ignorance, should i be using a charachter controller? or a rigidbody?

That’s one of those “it depends” questions. You generally use the character controller if you want non-physics, let’s say “quake style” or similar movement that still respects collisions.

You’d use the rigidbody when you want a character controller that follows physics, can be potentially affected by physics, and can interact with other physics objects.

In some situations they may end up being differen ways to get the same result.

Nonetheless, worth playing around with both.