Enabling cullingMask from script

I’m trying to check if a culling mask layer is enabled on a camera gameObject, and if it is to disable it and enable it again. This is in it’s own function so i can switch it on a given input. Here’s what I have so far:

    private void SwitchLayers()
    {
        if ((_PolaroidCamera.cullingMask & (12 << PlayerVisible)) != 0)
        {
            _PolaroidCamera.cullingMask = 12 & LayerMask.NameToLayer("Player Visible");
            
            Debug.Log("Player Visible IS visible to camera");
        }

        if ((_PolaroidCamera.cullingMask & (12 << PlayerVisible)) != 1)
        {
            _PolaroidCamera.cullingMask = 12 | LayerMask.NameToLayer("Player Visible");
            
            Debug.Log("Player Visible is NOT visible to camera");

        }
    }

I’ve seen other solutions talk about getting the index of the layer, and I have something like that:

    int PlayerVisible = LayerMask.NameToLayer("Player Visible");

…but I’m getting an error: “UnityException: NameToLayer is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead.”

I tried putting it somewhere else, but then it creates new errors elsewhere, and I’m not sure where else to put it, if it’s even necessary to begin with.

I already created the needed culling masks for my project.

I guess this should help

    private void SwitchLayers)
    {
        // Disabling
        _PolaroidCamera.cullingMask &= ~LayerMask.GetMask("Player Visible");

        // Enabling
        _PolaroidCamera.cullingMask |= LayerMask.GetMask("Player Visible");
    }

So, if I wanted to check if a layer was disabled/enabled, would it look like this:

if ((_PolaroidCamera.cullingMask &= ~LayerMask.GetMask("Player Visible")) != 0)
        {
            _PolaroidCamera.cullingMask |= LayerMask.GetMask("Player Visible");
            
            Debug.Log("Player Visible IS visible to camera");
        }

No, your if statement unsets the “Player Visible” flag in the culling mask and then checks if any flags are set in the culling mask. That’s because you are using &=, which will update the culling mask in-place and return its current value, which is then compared in != 0.

To check if a flag is set, use:

var playerVisible = LayerMask.GetMask("Player Visible");

if ((_PolaroidCamera.cullingMask & playerVisible) == playerVisible) {
    // Flag is set
}

if ((_PolaroidCamera.cullingMask & playerVisible) == 0) {
    // Flag is not set
}

If you know for sure that playerVisible has only a single flag, you can also use != 0 to check if the flag is set. But if it has multiple flags, that would check if any of the flags are set, not if all of them are.

@Adrian it kind of works. Every time it runs the SwitchLayers function, the first If statement is true and runs the nested code. But if I run it again, it runs the same If statement. This means the playerVisible mask isn’t being changed from false to true or visa versa. I even tried switching the contents of both If statements and it does the same.

Here’s a screenshot of the debug information:

And here’s the new code I have with current changes:

private void SwitchLayers()
    {
        var playerVisible = LayerMask.GetMask("Player Visible");
        
        if ((_ViewfinderCamera.cullingMask & playerVisible) == playerVisible)
        {
            _ViewfinderCamera.cullingMask |= playerVisible;
            
            Debug.Log("PlayerVisible IS visible to camera");
        }

        if ((_ViewfinderCamera.cullingMask & playerVisible) == 0)
        {
            _ViewfinderCamera.cullingMask &= playerVisible;
            
            Debug.Log("PlayerVisible is NOT visible to camera");
        }
    }

Can I ask you for what reason are you checking if layer is enabled or disabled if you’re anyway going to disable it and enable? Seems like you don’t really need to do this check

Swap the conditions, right now you’re trying to enable layer mask when it’s already enabled (in the first if statement) and trying to disable if it is already disabled (second if statement)

@Eyellen I’m trying to make a virtual camera that can take a picture of different layers, with the player being able to switch between the layers, and I’m doing this by enabling and disabling certain layers.

I could’ve done this by having multiple cameras looking at one layer, and just enabling and disabling cameras and render textures, but after a while a system like that can get messy, confusing and unreadable.

Well then you can just use these simple methods:

public bool IsEnabled(string layerName)
{
    return (camera.cullingMask & LayerMask.GetMask(layerName)) == 1;
}

public void SetLayer(string layerName, bool enabled)
{
    if (enabled)
        camera.cullingMask |= LayerMask.GetMask(layerName);
    else
        camera.cullingMask &= ~LayerMask.GetMask(layerName);
}

public void EnableAll()
{
    camera.cullingMask = ~0;
}

public void DisableAll()
{
    camera.cullingMask = 0;
}

This only works for layer 0 (with mask value 1), all other layers have a different mask value and this method will always return false for them.

This should be instead:

public bool IsEnabled(string layerName)
{
    var layerMask = LayerMask.GetMask(layerName);
    return (camera.cullingMask & layerMask) == layerMask;
}
1 Like

Oh yeah, thanks for the correction!

public bool IsEnabled(string layerName)
{
    var layerMask = LayerMask.GetMask(layerName);
    return (camera.cullingMask & layerMask) == layerMask;
}

public void SetLayer(string layerName, bool enabled)
{
    if (enabled)
        camera.cullingMask |= LayerMask.GetMask(layerName);
    else
        camera.cullingMask &= ~LayerMask.GetMask(layerName);
}

public void EnableAll()
{
    camera.cullingMask = ~0;
}

public void DisableAll()
{
    camera.cullingMask = 0;
}

How might I combine this code with an input? It looks like this code has several functions that must be called. Right now I have all of the code needed to toggle layer masks, nested in a separate function, and called from a getButtonDown function.

It depends on what you want to do, as far as I understood you, you want to disable specific layer and enable it again, though there is not sense in disabling layer and enabling it again in one frame

// This method disables and enables "Player Visible" layer.
private void DisableAndEnable()
{
      // This will disable "Player Visible" layer.
      SetLayer("Player Visible", false);

      // This will enable "Player Visible" layer.
      SetLayer("Player Visible", true);
}

Also you can’t call constructor in MonoBehaviour, instead use Awake or Start methods