Unity Layermask Helpers Script

Unity Layermask Helpers Script

Aug 28, 2023

Here is a nifty little script to help with layermasks in Unity.

In Unity, the layermasks use bitwise maths, which is quite confusing for beginners, and therefore it's difficult to get them the layermasks to behave as you'd like.

I developed this script for use in a game where I needed to dynamically change which layers collided with each other at different times. This script includes helper functions to easily combine and subtract layermasks.

The Methods

  • CombineLayerMasks - combines the layers from both masks into one.

  • SubtractLayerMask - removes all the layers from one layermask from another layermask.

  • CreateLayerMaskWithSingleLayer - creates a layermask containing a single layer.

  • AddSingleLayerToLayerMask - adds a single layer to an existing layermask.

  • RemoveLayerFromLayerMask - subtracts a single layer from a given layermask.

  • GetFirstSetLayer - this returns the first layer set in a layermask, and is used when you have a layermask you know has only one layer and need to know what that layer is.

The Script

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class LayerMaskHelpers : MonoBehaviour

{

// helper functions to make dealing with layermasks easier

// layermasks use bitwise maths, which is not very intuitive, and very tricky for beginners

// this helper class includes some descriptions of what the code is doing to help illustrate the techniques

public static LayerMask CombineLayerMasks(LayerMask maskOne, LayerMask maskTwo)

{

// combines all the layers in two separate layermasks

// returns a layermask that contains all layers that are in either maskOne or maskTwo

return maskOne | maskTwo;

}

public static LayerMask SubtractLayerMask(LayerMask mask, LayerMask layersToSubtract)

{

// subtract all layers in layersToSubtract from mask and return the remaining layers

return mask & ~layersToSubtract;

// by using the bitwise AND (&) and the bitwise NOT (~), the logic is returning the layers that are in mask but NOT also in layersToSubtract.

// we are 'flipping' layersToSubtract so that the layers we want to remove are all set to zero. Then the bitwise AND (&) keeps all the layers that are true in both.

// Effectively, this retains all the layers from mask unless they are enabled in layersToSubtract.

}

public static LayerMask CreateLayerMaskWithSingleLayer(string layerName)

{

// returns a layermask with JUST the layer provided

return LayerMask.NameToLayer(layerName);

}

public static LayerMask AddSingleLayerToLayerMask(LayerMask mask, string layerToAdd)

{

// bitshift (<<) is used to convert the value to the correct layer number

// the code is basically doing: get all the layers that are in mask PLUS (or, inclusive OR) the layer named in the layerToAdd property.

// if layerToAdd is already in mask OR it is in layerToAdd, include it in mask

mask = mask | (1 << LayerMask.NameToLayer(layerToAdd));

return mask;

}

public static LayerMask RemoveLayerFromLayerMask(LayerMask mask, string layerToRemove)

{

// this requires two steps

// first, we check if the layer we ask to remove is actually in the layermask - if not, we don't need to remove it

// the logic is "if the mask is identical to the mask with the unwanted layer added, then it means the mask includes the layer we want to remove"

// if the layer we want to remove is in the layermask we use the EXCLUSIVE OR (&) to remove that layer (i.e. if the layer is in both mask and layerToRemove, it is removed from mask).

if (mask == (mask | (1 << LayerMask.NameToLayer(layerToRemove))))

{

mask = mask ^ (1 << LayerMask.NameToLayer(layerToRemove));

}

return mask;

}

public static int GetFirstSetLayer(LayerMask mask)

{

// code obtained from Unity forums thread: https://forum.unity.com/threads/get-the-layernumber-from-a-layermask.114553/

// this returns a value to set an object's layer using a LayerMask with a single layer

// this is useful if you want to set a layer according to an inspector LayerMask field that holds multiple layers, but you only use it for a single layer

int value = mask.value;

if (value == 0) return 0; // Early out

for (int l = 1; l < 32; l++)

if ((value & (1 << l)) != 0) return l; // Bitwise

return -1; // This line won't ever be reached but the compiler needs it

}

}

Enjoy this post?

Buy DJ a coffee

More from DJ