Can Cinemachine Virtual Cameras have their own culling masks?

I have a Main Camera w/ Cinemachine brain. 2 Virtual cameras, A & B. I have a car model on its own “car” layer. I want virtual cam A to render the car, but when I cut to cam B, I want it to not render the car.

Can I do this?

It seems the Culling Mask option only exists on the Cinemachine Brain and I cannot adjust the culling mask for each virtual camera.

That’s correct. The culling mask is a feature of the Camera, not of the virtual camera. You would have to make a custom script to change the culling mask when vcam B activates, and change it back when vcam B deactivates.

Will this change in v3? Without being able to set culling masks, VirtualCameras aren’t actually VirtualCameras, they’re only half implemented – you can’t use them for shots where layers matter (which is a core feature of Unity, and many things rely on it working as-designed/built-in).

With CM3, the vcams are entirely decoupled from the layer system.

We have no specific plans to implement a feature to manipulate the camera’s layer mask, but we do provide an API (CinemachineExtension) so that you can implement custom extensions to drive properties that are not included in the core implementation.

This would be a good topic for a tutorial video. Taking note. Can you describe the use-case that you have in mind?

e.g. from a new asset I’m working on (and making sure it’s compatible/integrated with CineMachine core features) I’m testing at the moment (modular in-game player-editable weapons):

What’s happening:

  • Vcam-1 shows the player’s FPS/3PS camera (here: over-the-shoulder, can run around with FPS controls)
  • Vcam-2 shows all the modular weapons the player has collected, from a side-view, making it easy to re-build the weapon in different configurations
  • All GameObjects in the main game/map are on default layer
  • …but all GameObjects that only exist in player inventory are on an ‘Inventory’ layer
  • Vcam-1 is rendering 'Everything … [minus Inventory]"
  • Vcam-2 is rendering ‘Everything’
  • When blend 1->2 FINISHES, the mask switches to show ‘everything’ (inc. inventory)
  • When blend 2-1> STARTS, the mask switches to show ‘everything except inventory’

In general … vcam-2 probably wouldn’t render ‘everything’ (e.g. in an actual scene, I wouldn’t render all the nearby objects/etc – only the player’s location (Terrain + Buildings + large scene-items)) so that in ‘editing weapon’ mode the player camera doesn’t get interfered with by random nearby objects/physics.

Note also: this is Unity’s preferred way of handling things, and has the benefit that it isn’t just making the cameras render nicely, it’s also making sure Physics etc works correctly, automagically, because everything in Unity is (should be!) filtered by Layer/LayerMasks.

VCams don’t render, Cameras do. VCams are just “presets” to the most common camera properties. It’s up to you to respond to VCam switches to do anything to the camera that is not included in the preset.

On your other thread about blending events, I completely agree. CM should be notifying with plain events on BEGIN and END of a blending. It’s lazy for CM to leave that to hackish piggybacking sniffer scripts to try to figure out what’s going on inside the Brain.

1 Like

Right, but … specifically in Unity (other engines are designed differently) the culling-mask is a fundamental ‘common property’ of the Camera. All other Unity features/APIs/systems have been dependent since the very first versions of Unity on a shared concept that layermask defines the whole game/render/physics/everything logic. A camera’s cullingmask isn’t a ‘nice to have’, it’s essential to understanding what that camera will draw.

Or, to put it another way: pre-CineMachine every time I worked on a project with custom multi-camera setups (blending, timeline-style animations, even funky stuff like matrix interpolation (if you’re careful then you can smoothly blend Unity cameras from Orthographic → Perspective, even though lots of people on the forums don’t believe it ;))) … then we’ve had at least some variation in layermasks for the different cameras.

FWIW: my neatest solution so far is to take @Gregoryl 's example from the thread @halley1 referenced - OnCameraTransition / OnBlendComplete event - and modify it so that it generates a trio of callbacks:

class VirtualCameraReactToBlendInOut : MonoBehaviour
{
// ... various bits from @gregoryl's example, that then invoke these 3 callbacks:
public abstract void _OnVirtualCameraAnimateIn_Started( CinemachineVirtualCameraBase vcam );
public abstract void _OnVirtualCameraAnimateIn_Finished( CinemachineVirtualCameraBase vcam );
public abstract void _OnVirtualCameraAnimateOut_Started( CinemachineVirtualCameraBase vcam );
}

… and then subclass that to do mask updates, which seems to work well. I’m expecting/hoping to update/replace the base class sometime in 2025 (when CMv3 is supported in Unity production versions :)), and remove its hacky code, but I shouldn’t need to change the subclasses which are now independent, e.g.:

public class SetVirtualCamerasMask : VirtualCameraReactToBlendInOut
{
    public LayerMask cullingMaskWhileLive;
    private LayerMask _savedLayerMask;

    public override void _OnVirtualCameraAnimateIn_Started( CinemachineVirtualCameraBase vcam )
    {
    }

    public override void _OnVirtualCameraAnimateIn_Finished( CinemachineVirtualCameraBase vcam )
    {
        _savedLayerMask = Camera.main.cullingMask;
        Camera.main.cullingMask = cullingMaskWhileLive;
    }

    public override void _OnVirtualCameraAnimateOut_Started( CinemachineVirtualCameraBase vcam )
    {
        Camera.main.cullingMask = _savedLayerMask;
    }
}
1 Like

You can add a custom extension. This works like a charm for me

  1. Create the below class “CinemachineExtensionLayerMask”
  2. Click the “Add Extension” dropdown on the virtual camera and select “CinemachineExtensionLayerMask” from the list
  3. Configure the desired layer mask on the extension
public class CinemachineExtensionLayerMask : CinemachineExtension
{
    [SerializeField]
    private LayerMask _layers;

    protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    {
        Camera.main.cullingMask = _layers;
    }
}
4 Likes

Camera.main would bring issues in multi cam setup. However the workaround does not seem that simple … just have a look at CinemachinePostProcessing extension and it will chill your spine …

It’s not so bad. That extension has extra complexity for reasons of its own. To get the Unity Camera associated with a vcam, you can do:

Camera GetCamera(CinemachineVirtualCamera vcam)
{
    var brain = CinemachineCore.Instance.FindPotentialTargetBrain(vcam);
    return brain != null ? brain.OutputCamera : null;
}
2 Likes

This indeed seems way less complex, thanks very much @Gregoryl !

1 Like

Hey Im new to all this even C#, culling mask, virtual cameras. Im have a problem with my camera going Live when activated, it activates but stays in Standby and ive been trying to figure this out for 3 days and its frustrating me. Ive read other posts and i dont understand what anyones talking about. I have a vcam on a DollyCart thats fine in picture its CM vcam2. Player vcam1 Is my main virtual camera, and Shoot vcam3 is my aim in zoom cam all the settings are the same as Player vcam1 other then higher priority which does nothing by the way no matter what i have it at for Shoot cam3, and Field Of View is 25 instead of 40. Ive tried various ways in script and in inspector to fix this spoke with an AI for 2 days but every answer it gives is wrong, Ive messed with every setting, only thing Ive noticed is people talking about culling mask in cinemachine brain, which in mine theres nothing that says culling mask only my main camera not the virtual ones has a culling mask function in inspector, but everyone with my problem says this is the fix and i cant figure it out… I took 3 screen shots one with MainCamera Cinemachine Brain, Shoot vcam3 with PlayerShooting.cs, and Player vcam1 with ThirdPersonShottingController.cs. Can anyone tell my why my Shoot vcam3 activates but doesnt change from standby to Live? one thing Ive noticed is I have one of those DollyCart Cams that show the level before starting and my Shoot vcam3 says Live during the cut scene but once the main Virtual cam Player vcam1 starts it goes back into standby.

everything else works fine my animation and right mouse click Aim button all work fine just the cam dont leave standby once main VR cam kicks in

@aplusgreenlawn My friend, please consider using sentences and punctuation in your posts. It’s very hard to understand what you’re saying in your wall of text.

  1. The camera’s culling mask is a field in the Unity Camera component (not the CM Brain). Since your vcams are all on the Default layer, make sure that the culling mask includes Default.

  2. If your culling mask is ok and your vcam is still not going live, probably it’s the vcam Priority. If multiple vcams are active, the CM Brain will make Live the one with the highest Priority. If multiple vcams have that same highest Priority, then the most-recently-activated one will win.

My typings not the best, sorry. I think I may have figured it out while I was walking the dog. When I created my Player vcam1, I did some timeline thing with my CM vcam2 From the DollyCart on the DollyTrack to make My DollyCam smooth into my Player vcam1. And when I created my Shoot vcam3 I just duplicated my Player vcam1 and changed some settings, so I’m thinking that might have something to do with it. And thanks Gerg!

I dont know what happen, now I can’t find the timeline that was created for doly cam to player cam. Everything works as it should in GamePlay my “Aim” button works. The camera transition works! It just sits in standby though.

Shoot vcam3 has highest priority on my list but only activates when I press the “Aim” button (RightMouseClick), but it will not come out of Standby “Status”.
I also tried having my “PLayer vcam1” Deactivate/Activate when my “Shoot vcam3” is Activated/Deactivated. But “Player vcam1” stays Live “Status” even when Deactivated and lower Priority?

Do you have an active Timeline that is forcing Player vcam1? Timeline overrides the Priority system (and will even force-activate deactivated vcams).