Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Programatically switch between virtual cameras

Discussion in 'Cinemachine' started by RedactedProfile, Jul 13, 2017.

  1. RedactedProfile

    RedactedProfile

    Joined:
    Mar 7, 2015
    Posts:
    12
    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

    Code (CSharp):
    1. if(currentNode.getCamera() != null)
    2.         {
    3.             Debug.Log("Got Camera, lets try switching");
    4.             GameObject cam = currentNode.getCamera();
    5.          
    6.             cam.GetComponent<CinemachineVirtualCamera>().enabled = true; // <-- doesn't work
    7.         }
    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
     
    AlanMattano likes this.
  2. Adam_Myhill

    Adam_Myhill

    Joined:
    Dec 22, 2016
    Posts:
    342
  3. felixIksz

    felixIksz

    Joined:
    Sep 19, 2017
    Posts:
    5
    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.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class FlexibleCameraSwitch : MonoBehaviour {
    6.  
    7.     public GameObject[] cameraList;
    8.     private int currentCamera;
    9. void Start () {
    10.         currentCamera = 0;
    11.         for (int i = 0; i < cameraList.Length; i++){
    12.             cameraList[i].gameObject.SetActive(false);
    13.         }
    14.      
    15.         if (cameraList.Length > 0){
    16.             cameraList[0].gameObject.SetActive (true);
    17.         }
    18.     }
    19.    
    20. void Update () {
    21.         if (Input.GetMouseButtonUp(0)){
    22.             currentCamera ++;
    23.             if (currentCamera < cameraList.Length){
    24.                 cameraList[currentCamera - 1].gameObject.SetActive(false);
    25.                 cameraList[currentCamera].gameObject.SetActive(true);
    26.             }
    27.             else {
    28.                 cameraList[currentCamera - 1].gameObject.SetActive(false);
    29.                 currentCamera = 0;
    30.                 cameraList[currentCamera].gameObject.SetActive(true);
    31.             }
    32.         }
    33.     }
    34. }
    I have set up an example scenario to illustrate the question:
    upload_2018-4-3_11-4-42.png
     
  4. felixIksz

    felixIksz

    Joined:
    Sep 19, 2017
    Posts:
    5
    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!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class FlexibleCMCameraSwitch : MonoBehaviour {
    6.  
    7.     public GameObject[] cameraList;
    8.     private int currentCamera;
    9. void Start () {
    10.         currentCamera = 0;
    11.         for (int i = 0; i < cameraList.Length; i++){
    12.         }
    13.      
    14.         if (cameraList.Length > 0){
    15.             cameraList[0].gameObject.SetActive (true);
    16.         }
    17.     }
    18.  
    19. void Update () {
    20.         if (Input.GetMouseButtonUp(0)){
    21.             currentCamera ++;
    22.             if (currentCamera < cameraList.Length){
    23.                 cameraList[currentCamera - 1].gameObject.SetActive(false);
    24.                 cameraList[currentCamera].gameObject.SetActive(true);
    25.             }
    26.             else {
    27.                 //cameraList[currentCamera - 1].gameObject.SetActive(false);
    28.                 currentCamera = 0;
    29.                 cameraList[currentCamera].gameObject.SetActive(true);
    30.             }
    31.         }
    32.     }
    33. }
     
    Last edited: Apr 3, 2018
    AmdreTheNila, ibrina and AlanMattano like this.
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    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.
     
    TomTrottel and felixIksz like this.
  6. qVadro

    qVadro

    Joined:
    May 18, 2017
    Posts:
    24
    How to do smooth transition while switching virtual cameras? Without timeline
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    Set the default blend on the Brain:

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

    When you activate a new vcam, it will blend smoothly.
     
    qVadro likes this.
  8. daxiongmao

    daxiongmao

    Joined:
    Feb 2, 2016
    Posts:
    410
    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.
     
  9. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,500
    Is there a C# code example in Unity doc or learn that teach how to:
    GetComponent<CinemachineVirtualCamera>()
    ?
     
  10. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,500
    Ok probably
    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. public class CinemamachineController : MonoBehaviour
    5. {
    6.     [Header("Drag&Drop")]
    7.     public GameObject cinemachineVirtualCamera;
    8.  
    9.  
    10.     void Awake()
    11.     {
    12.         var Vcam = cinemachineVirtualCamera.GetComponent<CinemachineVirtualCamera>();
    13.         if (Vcam == null) Debug.LogError("A component cinemachineVirtualCamera is missing\n");
    14.     }
    15. }
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    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.
     
    AlanMattano likes this.
  12. danpos2506

    danpos2506

    Joined:
    Feb 29, 2020
    Posts:
    14
    I've put a few videos together on this:



     
    citycat3000 and PabloCostas like this.
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,623
    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.
     
  14. StriderRouga

    StriderRouga

    Joined:
    May 11, 2021
    Posts:
    18
    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().
     
  15. StriderRouga

    StriderRouga

    Joined:
    May 11, 2021
    Posts:
    18
    it seems one of my other scripts was the cause of my issue. awesome tutorials danpos2506, they helped me a lot!