Search Unity

Question Cannot change the main camera's culling mask while blending between two CinemachineVirtualCamera

Discussion in 'Cinemachine' started by Ender_the_Developer, May 21, 2023.

  1. Ender_the_Developer

    Ender_the_Developer

    Joined:
    Apr 26, 2020
    Posts:
    2
    Hello, I am trying to blend two CinemachineVirtualCameras with an "Ease in" blend and also changing the CullingMask of the main Camera at the same time. But when I'm doing it, the blending stops as soon as the cullingMask changed.

    I tried putting the mask modification in a coroutine but nothing changed, the blending freezes if it isn't completed by the time the mask is changed.

    Is this a bug or something normal and what should I do ?

    Here is the code I use to do all this :

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MapManager : MonoBehaviour
    6. {
    7.     [SerializeField] private GameObject freeLookCamera;
    8.     [SerializeField] private GameObject mapCamera;
    9.     [SerializeField] private LayerMask layerMask;
    10.     private Camera cam;
    11.     private LayerMask oldMask;
    12.  
    13.     void Start()
    14.     {
    15.         cam = Camera.main;
    16.     }
    17.  
    18.     public void OpenMap()
    19.     {
    20.         oldMask = cam.cullingMask;
    21.         cam.cullingMask = layerMask;
    22.         freeLookCamera.SetActive(false);
    23.         mapCamera.SetActive(true);
    24.     }
    25.  
    26.     public void CloseMap()
    27.     {
    28.         cam.cullingMask = oldMask;
    29.         freeLookCamera.SetActive(true);
    30.         mapCamera.SetActive(false);
    31.     }
    32. }
    OpenMap and CloseMap are called when I want to blend freeLookCamera and mapCamera.

    Thank you for your answer !
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    Yes, there is a little gotcha in Cinemachine: only vcams that are on layers included in the camera's culling mask can drive the camera. So, probably when you change the culling mask, the new value doesn't include the layer that the cameras are on. The solution is to put all the vcams on a layer that is always included in the culling mask.
     
  3. Ender_the_Developer

    Ender_the_Developer

    Joined:
    Apr 26, 2020
    Posts:
    2
    Thank you, now it works perfectly !
     
    Gregoryl likes this.
  4. Gearknacks

    Gearknacks

    Joined:
    May 25, 2023
    Posts:
    1
    From the provided code, it appears that you're changing the cullingMask property of the main camera immediately after activating or deactivating the cameras. This can cause the blending to stop prematurely because the camera blending is likely happening in the next frame update.

    To ensure that the blending completes before changing the cullingMask, you can use a coroutine. However, based on your description, it seems that using a coroutine alone didn't solve the issue. In that case, you can try using a coroutine along with a delay to give enough time for the blending to finish before modifying the cullingMask.

    Here's an updated version of your code that incorporates a coroutine and delay to achieve the desired blending and cullingMask modification:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MapManager : MonoBehaviour
    6. {
    7.     [SerializeField] private GameObject freeLookCamera;
    8.     [SerializeField] private GameObject mapCamera;
    9.     [SerializeField] private LayerMask layerMask;
    10.     private Camera cam;
    11.     private LayerMask oldMask;
    12.  
    13.     void Start()
    14.     {
    15.         cam = Camera.main;
    16.     }
    17.  
    18.     public void OpenMap()
    19.     {
    20.         oldMask = cam.cullingMask;
    21.         cam.cullingMask = layerMask;
    22.         freeLookCamera.SetActive(false);
    23.         mapCamera.SetActive(true);
    24.  
    25.         StartCoroutine(BlendAndModifyCullingMask());
    26.     }
    27.  
    28.     public void CloseMap()
    29.     {
    30.         cam.cullingMask = oldMask;
    31.         freeLookCamera.SetActive(true);
    32.         mapCamera.SetActive(false);
    33.     }
    34.  
    35.     private IEnumerator BlendAndModifyCullingMask()
    36.     {
    37.         yield return new WaitForSeconds(0.1f); // Adjust the delay as needed
    38.  
    39.         // Additional delay to ensure the blending is completed
    40.         yield return new WaitForSeconds(cam.GetComponent<Cinemachine.CinemachineBrain>().m_DefaultBlend.BlendTime);
    41.  
    42.         cam.cullingMask = layerMask;
    43.     }
    44. }
    45.  

    In the updated code, the BlendAndModifyCullingMask coroutine is called after activating the map camera and deactivating the free look camera. It introduces a short delay (0.1 seconds in this example) before modifying the cullingMask. Additionally, there's an extra delay equal to the blend time of the Cinemachine virtual cameras to ensure the blending is fully completed before modifying the cullingMask.

    You can adjust the delay values as per your specific requirements.