Programatically switch between virtual cameras

Good day,

Simple question: I’ve got some CineMachine virtual cameras setup around my scene. In my C# script I’ve got a reference to the gameobject that has the CinemachineVirtualCamera component attached to it as so

if(currentNode.getCamera() != null)
        {
            Debug.Log("Got Camera, lets try switching");
            GameObject cam = currentNode.getCamera();
         
            cam.GetComponent<CinemachineVirtualCamera>().enabled = true; // <-- doesn't work
        }

Frankly, this is all the built in Scripting example gives me in terms of how to deal with this.

I do understand that the example is simply disabling it’s highest priority camera and thus falling back onto the only other virtual camera in the scene and then re-enabling it, which is neat, but it and the documentation lacks solid examples of how to programatically switch the current active live camera.

Any ideas?


Edit, because I cant seem to delete

You know when you post something and you immediately find the solution? Yeah, all I had to do was bump up the camera priority and Cinemachine actively switches it out

yay

1 Like

Ha, good news. Yes the priority system has a lot of power. There’s a little blurb on it in another thread:

Hello,
I’ve been searching for a solution for some time but I couldn’t figure out how to write a working script for my case.

I would like to have a flexible camera switch code that can be extended depending on different scenarios.
In some scenes I have set up several cameras on the same node, rendering different layers with different replacement shaders (meaning that it’s absolutely necessary for each camera to have their own camera component and CM brain, right? Therefore I can only store them in a common node, which makes it necessary to refer to them as a game object).

The script I have right now works just fine with traditional Unity cameras (without CM used), but it won’t switch between CM cameras. I have attempted several times to write it referring to virtual cameras but it never worked.

I would highly appreciate any tips on the issue, as the CM API is very mysterious to me being a beginner developer.

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

public class FlexibleCameraSwitch : MonoBehaviour {

    public GameObject[] cameraList;
    private int currentCamera;
void Start () {
        currentCamera = 0;
        for (int i = 0; i < cameraList.Length; i++){
            cameraList[i].gameObject.SetActive(false);
        }
      
        if (cameraList.Length > 0){
            cameraList[0].gameObject.SetActive (true);
        }
    }
   
void Update () {
        if (Input.GetMouseButtonUp(0)){
            currentCamera ++;
            if (currentCamera < cameraList.Length){
                cameraList[currentCamera - 1].gameObject.SetActive(false);
                cameraList[currentCamera].gameObject.SetActive(true);
            }
            else {
                cameraList[currentCamera - 1].gameObject.SetActive(false);
                currentCamera = 0;
                cameraList[currentCamera].gameObject.SetActive(true);
            }
        }
    }
}

I have set up an example scenario to illustrate the question:

Never mind, I figured out a solution.
In case anyone is wondering, I’d like to leave some tips here.

It works in a linear, looping manner: it switches to the next camera in the list when you click. You should set the priority of the CM virtual cameras from high to low: with the brain camera at the end of the list.

For instance, say you wanna have 3 cameras in your scene in the following order:
VirtualCamera A (priority of CamA>priority CamB)
VirtualCamera B (priority of CamB>priority CamC)
Brain VirtualCamera C .

Create as many virtual cameras to the same brain, and as many brains as you want (multiple brain method was already explained elsewhere). Most importantly, the brain should always stay at the bottom of the hierarchy of it’s vCam children. Adding Brain and Virtual Cameras should be the last step, as CM brains have a funky way of referring to vCam children when you wanna change it afterwords.

Here is the code. Cheers!

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

public class FlexibleCMCameraSwitch : MonoBehaviour {

    public GameObject[] cameraList;
    private int currentCamera;
void Start () {
        currentCamera = 0;
        for (int i = 0; i < cameraList.Length; i++){
        }
      
        if (cameraList.Length > 0){
            cameraList[0].gameObject.SetActive (true);
        }
    }
  
void Update () {
        if (Input.GetMouseButtonUp(0)){
            currentCamera ++;
            if (currentCamera < cameraList.Length){
                cameraList[currentCamera - 1].gameObject.SetActive(false);
                cameraList[currentCamera].gameObject.SetActive(true);
            }
            else {
                //cameraList[currentCamera - 1].gameObject.SetActive(false);
                currentCamera = 0;
                cameraList[currentCamera].gameObject.SetActive(true);
            }
        }
    }
}
4 Likes

If you have a vcam parented to a brain, you’re doing it wrong. The setup should be something like this:

GameObject 1:

  • Unity Camera component, layer mask includes Layer A and not Layer B
  • CM Brain component

Game Object 2:

  • Unity Camera component, layer mask includes Layer B and not Layer A
  • CM Brain component

Game Object 3:

  • On layer A
  • CM Virtual Camera component

Game Object 4:

  • On layer A
  • CM Virtual Camera component

Game Object 5:

  • On layer B
  • CM Virtual Camera component

…and so on

GO1 is a Unity Camera whose transform will be driven by the vcams in GO3 and GO4.
GO2 is a Unity Camera whose transform will be driven by the vcam in GO5.
and so on

They are all separate game objects, not parented to each other.

2 Likes

How to do smooth transition while switching virtual cameras? Without timeline

Set the default blend on the Brain:

4072423--354901--upload_2019-1-7_11-59-53.png

When you activate a new vcam, it will blend smoothly.

1 Like

I also think you can make a virtual camera active by disable then enable it. If it is already enabled.
When all cameras have same priority.

Have to do it when teleporting the targets.

Is there a C# code example in Unity doc or learn that teach how to: GetComponent<CinemachineVirtualCamera>() ?

Ok probably

using UnityEngine;
using Cinemachine;

public class CinemamachineController : MonoBehaviour
{
    [Header("Drag&Drop")]
    public GameObject cinemachineVirtualCamera;
  

    void Awake()
    {
        var Vcam = cinemachineVirtualCamera.GetComponent<CinemachineVirtualCamera>();
        if (Vcam == null) Debug.LogError("A component cinemachineVirtualCamera is missing\n");
    }
}

Instead of doing public GameObject cinemachineVirtualCamera;, why not do public CinemachineVirtualCamera vcam; ? That way, the inspector would not let you drop a non-CinemachineVirtualCamera object there.

1 Like

I’ve put a few videos together on this:

2 Likes

We’re always happy to see Cinemachine tutorials, so thanks for that.

One thing: there is a shortcut you can use instead of the camera switcher class. Set all the virtual cameras to the same priority and call vcam.MoveToTopOfPrioritySubqueue() whenever you want to make a specific vcam the active one. Job done.

8 Likes

Hi there! I’m trying to do the same kind of thing but with virtual cameras that follow the player and have confiners. The cameras are switching nicely but the box colliders are being removed from their slots in the confiner as soon as I hit play and then come back when I go back to editing. Any idea what could be causing this? I’ve set up my camera switching script on colliders for each of the rooms and to switch the camera I’m using vcam.MoveToTopOfPrioritySubqueue().

it seems one of my other scripts was the cause of my issue. awesome tutorials danpos2506, they helped me a lot!