Yesterday I was working on making layers appear and disappear programmatically in Unity3D. The Unity code>Camera</code> class has a culling mask so that each camera can be set to only display a subset of the available layers. This is handy for placing 3D objects in one layer visible by the main camera, and say the GUI in another layer visible by a different camera. This can be setup using the camera’s culling mask dropdown in the editor. However, I wanted to be able to change the visible layers during runtime in response to a player’s actions (pressing a key will make a grid appear/disappear over the playing area).
To change the culling mask programmatically some bitfield maths is
required. Each layer is represented by a bit in an integer. Layer 12 is
000000000000000000100000000000
- the twelfth bit in a
32-bit integer mask. The culling mask itself is just the combination
(bitwise OR) of these layers. Thus, if the culling mask is
000000000010000000100000001000
(equivalent to the number
526344), the 4th, 12th and 20th layers
would be displayed as the 4th, 12th and
20th bits are turned on. To do this in code, first find the
number of the layer and then shift a bit this number of places, then add
or remove this from the mask. For example, to add the “Enemy” layer to
the mask would be: cam.cullingMask \|= 1 \<\<
LayerMask.NameToLayer(“Enemy”);
. Other bitwise operations can
remove layers.
I find this messy. I prefer my code to be a little more explicit and
readable. So I wrote a set of class
extensions for
the Camera
to add a better way of manipulating the culling
mask. Just add the class below into your project and then
cam.LayerCullingShow(“Enemy”)
will add the “Enemy” layer to
the cam. Similarly, cam.LayerCullingHide(“Enemy”)
will
remove the layer; cam.LayerCullingIncludes(“Enemy”)
will
tell you whether it is being displayed or not; and
cam.LayerCullingToggle(“Enemy”)
will flip the visibility of
the “Enemy” layer. If preferred, the layer mask can be passed as a
parameter rather than the layer’s name. Enjoy.
// Copyright 2014 Jarrah Technology (http://www.jarrahtechnology.com). All Rights Reserved.
using UnityEngine;
public static class CameraExtensions {
public static void LayerCullingShow(this Camera cam, int layerMask) {
cam.cullingMask |= layerMask;
}
public static void LayerCullingShow(this Camera cam, string layer) {
LayerCullingShow(cam, 1 << LayerMask.NameToLayer(layer));
}
public static void LayerCullingHide(this Camera cam, int layerMask) {
cam.cullingMask &= ~layerMask;
}
public static void LayerCullingHide(this Camera cam, string layer) {
LayerCullingHide(cam, 1 << LayerMask.NameToLayer(layer));
}
public static void LayerCullingToggle(this Camera cam, int layerMask) {
cam.cullingMask ^= layerMask;
}
public static void LayerCullingToggle(this Camera cam, string layer) {
LayerCullingToggle(cam, 1 << LayerMask.NameToLayer(layer));
}
public static bool LayerCullingIncludes(this Camera cam, int layerMask) {
return (cam.cullingMask & layerMask) > 0;
}
public static bool LayerCullingIncludes(this Camera cam, string layer) {
return LayerCullingIncludes(cam, 1 << LayerMask.NameToLayer(layer));
}
public static void LayerCullingToggle(this Camera cam, int layerMask, bool isOn) {
bool included = LayerCullingIncludes(cam, layerMask);
if (isOn && !included) {
LayerCullingShow(cam, layerMask);
} else if (!isOn && included) {
LayerCullingHide(cam, layerMask);
}
}
public static void LayerCullingToggle(this Camera cam, string layer, bool isOn) {
LayerCullingToggle(cam, 1 << LayerMask.NameToLayer(layer), isOn);
}
}
Comments: I have removed the commenting system (for privacy concerns), below are the comments that were left on this post before doing so…
ahmad khawaja @ 2014-08-25 - Excellent …I was pretty confused about the concept. Your example helped me a lot
Samantha Alder @ 2016-01-24 - Excellent …I was pretty baffled by the idea. Your example solved the problem a lot