Read camera current rotation and set mouselook

I have an issue that I have been banging my head against for a little bit. Hopefully you amazing people can assist.
I am trying to make it so that when the game starts the camera is in freelook mode. When the player presses LeftControl the camera locks into position and the player can now fly the ship without much worry about losing their view. The ship can pitch and yaw of course. The issue is that when I pitch or yaw and then go into freelook mode the camera always resets the view to 0
The code below is my attempt to fix it. But of course it does not work.

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

public class CameraController : MonoBehaviour
{
    public Camera CockpitCam;
    public GameObject PanelControllerScript;
    public bool CamOverRide;
    public float ScrollSensitivity = 4;
    public float speed = 3;
    public float Zoom = 60f;
    private Quaternion CamPos;
    Vector2 rotation;

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
        rotation.y = 90;
        transform.eulerAngles = (Vector2)rotation;
        CockpitCam.enabled = true;
        CamOverRide = false;
    }

    void Update()
    {

        CamPos = CockpitCam.transform.rotation;
        Debug.Log(CamPos);
        FreeLookCam();
        if (Input.GetKeyDown(KeyCode.LeftControl))
        {
            if (CamOverRide == false)
            {
                CamOverRide = true;
            }
            else if (CamOverRide == true)
            {
                transform.rotation = CamPos;
                CamOverRide = false;
            }
        }
        CockpitCam.enabled = true;
    }
    private void FreeLookCam()
    {
        if (CamOverRide == false)
        {
            if (CockpitCam == true)
            {
                rotation.y += Input.GetAxis("Mouse X");
                rotation.x += -Input.GetAxis("Mouse Y");
                transform.eulerAngles = (Vector2)rotation * speed;
                if (Input.GetAxis("Mouse ScrollWheel") < 0)
                {
                    Zoom = Zoom + ScrollSensitivity;
                    CockpitCam.fieldOfView = Zoom;
                }
                if (Input.GetAxis("Mouse ScrollWheel") > 0)
                {
                    Zoom = Zoom - ScrollSensitivity;
                    CockpitCam.fieldOfView = Zoom;
                }
                if (Input.GetKeyDown(KeyCode.L))
                {
                    CockpitCam.fieldOfView = 60;
                    rotation.y = 90;
                    rotation.x = 0;
                    transform.eulerAngles = (Vector2)rotation;
                }
            }
        }
    }
}

Any ideas?

Hi @noyesgreene

I didn’t read your code but I’d do the following…

“The issue is that when I pitch or yaw and then go into freelook mode the camera always resets the view to 0”

If you want to start free look mode from whatever rotation you have currently, then don’t change rotation value when entering free look mode. Only take input and adjust camera rotation based on that.

Thanks for the prompt reply @eses I’ll give that a try! I think the reason it is snapping to 0 when entering freelook mode is because the mouse location is at 0

@eses would that mean setting up if statements so that “if the mouse moves this direction, then translate the camera” sort of thing?

@noyesgreene

You should be able to enter/exit free look mode properly if you use local rotations. I’ve done this several times. That way you can look around then lerp back to locked view, no matter if ship is facing any direction… or even if it is upside down. Also, when you are flying around, camera simply follows as a child of the ship, maybe with some additional animation.

A snippet I’ve created, take a look and/or try it. Note this is not a perfect solution it won’t work if you want to cancel lerping to locked camera half way. FwdDir is local rotation of ship camera stored in Start. CamRot is vector2 that stores x and y rotation relative to default rotation.

void Update()
{
    if (Input.GetKeyDown(KeyCode.F))
    {
        freeMode = !freeMode;

        if (freeMode)
        {
            cam.transform.localRotation = fwdDir;
            camRot.Set(0, 0);
        }
    }

    if (freeMode)
    {
        camRot.x += Input.GetAxis("Mouse Y") * sensitivity;
        camRot.y += Input.GetAxis("Mouse X") * sensitivity;
        cam.transform.localRotation = Quaternion.Euler(camRot.x, camRot.y, 0);
    }
    else
    {
        if (cam.transform.localRotation != fwdDir)
        {
            cam.transform.localRotation = Quaternion.RotateTowards(cam.transform.localRotation, fwdDir, Time.deltaTime * 50f);
        }
    }
}
1 Like

@eses ,
Your script worked like a charm. Turns out that part of my issue was my model was not at 0,0,0 in unity so I was dealing with two different coordinate systems in local. Once I took my ship to 0,0,0 in unity everything made sense.

1 Like