Free moving camera in 3d

Hello,
I hope someone here can help me. I want to implement a camera that can switch between 3rd person view (orbit camera) and a free moving mode (like in League of Legends but in 3 dimensional space) by pressing a button. In the free moving mode the camera should behave like it does in the Scene View of Unity.
I use the Freelook Camera from Cinemachine because of the orbit mode.
However, when I put the camera in 3rd person view and then set it back to free moving, it does some weird things. The Main Camera rotates on the Z-axis (although I explicitly set the Z-axis of the Freelook Camera to 0), which causes it to move sometimes mirrored. What am I doing wrong?

My code: (component of the freelook camera)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Cinemachine;
using TMPro;

public class FreeMovingCamControl : MonoBehaviour
{
    [Header("Rotation speed")]
    public float speedH;
    public float speedV;

    [Header("Movement speed")]
    public float movementSpeed;

    [Header("Scrolling speed")]
    public float scrollSpeed;

    [Header("Player transform")]
    public Transform olaf;

    private float horizontal;
    private float vertical;
    private Vector3 newPos;
    private Vector3 newRot;
    private CinemachineFreeLook cinemachine;

    [Header("UI")]
    public bool cameraLocked = true;
    public TextMeshProUGUI btText;

    void Awake()
    {
        // Initialize variables
        horizontal = speedH;
        vertical = speedV;
        cinemachine = transform.GetComponent<CinemachineFreeLook>();
        if (cameraLocked)
        {
            LockCam();
        }
        else
        {
            UnlockCam();
        }
    }

    void Update()
    {
        if (cameraLocked) // orbit camera
        {
            if (Input.GetKeyDown("space"))
            {
                UnlockCam();
            }
            if (Input.GetMouseButton(1))
            {
                cinemachine.m_XAxis.m_InputAxisName = "Mouse X";
                cinemachine.m_YAxis.m_InputAxisName = "Mouse Y";
            }
            else
            {
                cinemachine.m_XAxis.m_InputAxisName = "";
                cinemachine.m_YAxis.m_InputAxisName = "";
                cinemachine.m_XAxis.m_InputAxisValue = 0;
                cinemachine.m_YAxis.m_InputAxisValue = 0;
            }

            float zoom_direction = Math.Sign(Input.GetAxis("Mouse ScrollWheel"));
            if (zoom_direction != 0f) // forward
            {
                cinemachine.m_Orbits[0].m_Height -= zoom_direction * scrollSpeed;
                cinemachine.m_Orbits[1].m_Radius -= zoom_direction * scrollSpeed;
                cinemachine.m_Orbits[2].m_Height += zoom_direction * scrollSpeed;
            }
        }
        else
        {
            if (Input.GetKeyDown("space"))
            {
                LockCam();
            }
            if (Input.GetMouseButton(1)) // right mouse button pressed -> rotate camera
            {
                horizontal += speedH * Input.GetAxis("Mouse X");
                vertical -= speedV * Input.GetAxis("Mouse Y");

                transform.eulerAngles = new Vector3(vertical, horizontal, 0.0f);
            }
            else // prevent rotating camera without clicking any button (just cinemachine stuff that happens otherwise)
            {
                cinemachine.m_XAxis.m_InputAxisName = "";
                cinemachine.m_YAxis.m_InputAxisName = "";
                cinemachine.m_XAxis.m_InputAxisValue = 0;
                cinemachine.m_YAxis.m_InputAxisValue = 0;
            }
            if (Input.GetMouseButton(2)) // mouse wheel pressed -> move camera upwards or sideways
            {
                newPos = transform.position;
                newPos.y -= speedV * Input.GetAxis("Mouse Y");
                transform.position = newPos;
                //transform.Translate(-Camera.main.transform.right * Input.GetAxisRaw("Mouse X") * movementSpeed, Space.World);
                transform.Translate(-transform.right * Input.GetAxisRaw("Mouse X") * movementSpeed, Space.World);
                Debug.Log("Camera main: " + Camera.main.transform.right);
                Debug.Log("Freelook: " + transform.right);
            }

            float zoom_direction = Math.Sign(Input.GetAxis("Mouse ScrollWheel")); // positive -> 1, negative -> -1, zero -> 0
            if (zoom_direction != 0f) // scrolling moves camera forwards or backwards
            {
                transform.Translate(Camera.main.transform.forward * scrollSpeed * zoom_direction, Space.World);
            }
        }

    }

    public void UnlockCam()
    {
        cameraLocked = false;
        btText.text = "cam free";
        cinemachine.m_Follow = null;
        cinemachine.m_LookAt = null;
        cinemachine.GetComponent<CinemachineCollider>().enabled = false;
    }

    public void LockCam()
    {
        horizontal = transform.forward.y;
        vertical = transform.forward.x;
        cameraLocked = true;
        btText.text = "cam locked";
        cinemachine.m_Follow = olaf;
        cinemachine.m_LookAt = olaf;
        transform.eulerAngles = Vector3.zero;
        cinemachine.GetComponent<CinemachineCollider>().enabled = true;
    }

    public void OnButtonClick()
    {
        if (cameraLocked)
        {
            UnlockCam();
        }
        else
        {
            LockCam();
        }
     }

}

My sense is that maybe you’re thinking about Virtual Cameras in a way that isn’t as helpful as it could be. @Gregoryl could certainly give you more precise advice, but in general, I wouldn’t try to do this with with a single VCam, but rather with two, and then transition between them.

Cam1 would be the Freelook camera.
Cam2 would be the free moving camera (again, I’ll defer to Greg on what the best settings would be).

Then you simply alter camera priorities when you want to swap between them. No coding required (well, except for the priority swap).

1 Like

Ahh thank you! It works now and I also got a nice transition between the two cameras without doing anything :slight_smile:

2 Likes