Camera Script Question

Hi guys,

i have been developing a 3D fantasy game for PC/Mac, and i have a player character in third person.
My goal for the main camera is that it follows the player everywhere and that the player can rotate it around the the character with the mouse.
For the second purpose i’ve found this script online and it works properly, but now, how can i make the camera follow the player always at the same distance from it?

Best regards and thanks for your time.

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


public class CameraRotate : MonoBehaviour {

    public float turnSpeed = 4.0f;        // Speed of camera turning when mouse moves in along an axis
    public float panSpeed = 4.0f;        // Speed of the camera when being panned
    public float zoomSpeed = 4.0f;        // Speed of the camera going back and forth

    private Vector3 mouseOrigin;    // Position of cursor when mouse dragging starts
    private bool isPanning;        // Is the camera being panned?
    private bool isRotating;    // Is the camera being rotated?
    private bool isZooming;        // Is the camera zooming?

    //
    // UPDATE
    //

    void Update ()
    {
        // Get the left mouse button
        if(Input.GetMouseButtonDown(0))
        {
            // Get mouse origin
            mouseOrigin = Input.mousePosition;
            isRotating = true;
        }

        // Get the right mouse button
        if(Input.GetMouseButtonDown(1))
        {
            // Get mouse origin
            mouseOrigin = Input.mousePosition;
            isPanning = true;
        }

        // Get the middle mouse button
        if(Input.GetMouseButtonDown(2))
        {
            // Get mouse origin
            mouseOrigin = Input.mousePosition;
            isZooming = true;
        }

        // Disable movements on button release
        if (!Input.GetMouseButton(0)) isRotating=false;
        if (!Input.GetMouseButton(1)) isPanning=false;
        if (!Input.GetMouseButton(2)) isZooming=false;

        // Rotate camera along X and Y axis
        if (isRotating)
        {
            Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);

            transform.RotateAround(transform.position, transform.right, -pos.y * turnSpeed);
            transform.RotateAround(transform.position, Vector3.up, pos.x * turnSpeed);
        }

        // Move the camera on it's XY plane
        if (isPanning)
        {
            Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);

            Vector3 move = new Vector3(pos.x * panSpeed, pos.y * panSpeed, 0);
            transform.Translate(move, Space.Self);
        }

        // Move the camera linearly along Z axis
        if (isZooming)
        {
            Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);

            Vector3 move = pos.y * zoomSpeed * transform.forward;
            transform.Translate(move, Space.World);
        }
    }
}

You can attach your camera to the player object in the hierarchy. That should do

I think what would help you most is knowing what that script does versus what your camera is supposed to be doing.

so, mouse 0 is the Left mouse button, if you hold it down it needs to rotate, but It specifically rotates around the camera, not the player. So changing it to something like:

transform.RotateAround(player.position, transform.right, -pos.y * turnSpeed);
transform.RotateAround(player.position, Vector3.up, pos.x * turnSpeed);

This will rotate your camera around the player’s location, rather than where the camera is.

panning is pretty much a no no, if you want to keep the camera fixed on the player. So the whole panning thing should not work with that setup.

zooming is quite a bit different as well. Instead of moving the camera, we need to simply move a variable (float) that will control that zoom factor. For this, you will need a maximum and minimum zoom.

Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);

zoomDistance += -pos.y * zoomRate;
zoomDistance = Mathf.Clamp(zoomDistance, 1, 20);

With that, you then need to re position your camera on the LateUpdate

void LateUpdate(){
transform.position = player.position;
transform.Translate(Vector3.back * zoomDistance, Space.Self);
}

Of course, I didn’t test any of this, but the theory is sound.

Additions:

You should consider using euler angles instead of rotation. With this, you could use angular limits for the euler. (like -60 to 60 degrees) This prevents the player from becoming disoriented.

Thank you so much bigmisterb! The rotation around the player works properly! Just one question: Where should i put these line of codes?

Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
    zoomDistance += -pos.y * zoomRate;
    zoomDistance = Mathf.Clamp(zoomDistance, 1, 20);

Best regards.

That would be in place of the isZooming part. You would of course have to add the zoomDistance variable at the top with a default value. (say 5)

Thanks, it works properly. Now, for making the camera follows the player i used this second script:

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

public class FollowPlayer : MonoBehaviour {

    public GameObject player;
    private Vector3 cameraLocation;
    // Use this for initialization
    void Start () {
        cameraLocation = transform.position - player.transform.position;
    }

    // Update is called once per frame
    void Update () {
        transform.position = player.transform.position + cameraLocation;
    }
}

But if i add this second script too, the camera follows the player, but it does not rotate around the player well. How can i make follows the player well?