- Home /
The question is answered, right answer was accepted
How do I use layermasks?
Layermasks took me a while to figure out and get working correctly, and I've seen a few people asking about them on the forums, so I thought I'd add a little something to help anyone who may be struggling with them.
The question is: How do I use/create layermasks to use with, e.g., Physics.Raycast or other Physics functions? For those who don't know: a layermask allows you to specify certain layers to exclude/include in certain physics functions.
This question and answers have been very helpful, thanks.
Answer by Stelimar · Dec 07, 2009 at 12:12 AM
layermasks work by setting bits in an integer value to 0 (false) or 1 (true), which represent whether or not to test against a certain layer. The first bit from the right is used for layer 1, the second for layer 2, etc. So a value of 00000101 (decimal value of 5), which has the first and third bit set to 1 (true), will test ONLY against layers one and three.
Using bit shifting to create a layermask
The easiest way to produce a layermask is using the bit shift operator (<<). What this does is move each bit in an value to the left. So if you have a value of 6 (binary value of 00000110), and shift it two places to the left, you will be given a value of 24 (binary 00011000).
Remember that a value of 1 in decimal is 00000001 in binary. So if you bit shift 1 by n places to the left, you will end up with the nth bit being 1 and all other bits being 0. Based on this, the following code will produce a layermask which can be used to only test against the given layer:
var layer : int = 3;
var layermask : int = 1 << layer;
layermask will turn out to be 4 in decimal (00000100). Notice that the third bit is 1 (true).
Combining layermasks
To produce a layermask which will test against more than one layer, you can use the binary OR operator (|) to produce a new layermask. A bit in the new layermask is true if the corresponding bit was true in either one of the layermasks it was made from:
var layer1 : int = 3;
var layer2 : int = 5;
var layermask1 : int = 1 << layer1;
var layermask2 : int = 1 << layer2;
var finalmask : int = layermask1 | layermask2; // Or, (1 << layer1) | (1 << layer2)
// The bits look like this:
// (00000001) First bit is true in layermask1
// (00000100) Third bit is true in layermask2
// (00000101) Both first and third bit are true in finalmask
(Note that adding layermasks together with (+) is usually not wanted. For example, adding two layermasks that both contain the same layer, such as 00000011 (layer 1 and 2) and 00000110 (layer 2 and 3) would produce 00001001 (layer 1 and 4), while with the bitwise OR operator (|) you get 00000111 (layer 1, 2, and 3) as expected.)
Inverting a layermask
To test for all layers except the given layer, just use the bit inverse operator (~). The bit invert operator takes every bit in an integer, and swaps it from 0 to 1 or vice versa. So ~00000010 equals 11111101, which would test for every layer except layer 2.
Note that if there are two layers you want to exclude, you need to combine the bitmasks with the OR operator before inverting:
var layer1 : int = 3;
var layer2 : int = 5;
var layermask : int = ~((1 << layer1) | (1 << layer2)) // NOT ~(1 << layer1) | ~(1 << layer2)
This would give you a value of 11101011.
I hope this helped somebody!
You shouldn't add the layermasks together. You should use the binary OR operator.
There's another typo in this code, but I haven't reached the magic limit to be able to fix it! The 4th line in the 2nd example code has 2 << layer2 whereas it should read 1 << layer2
You have some off-by-ones. In the first code segment you say that 1<<3
is 100, but it's really 1000 (it shifts over by 3.) At the very top you say 001 is layer1, but it's really layer 0. In your next code segment, with layers 3 and 5, the results should be 3:1000, 5:100000 and (3|5):101000
1000 0000 0000 0000 would never be 1. A little-endian processor would store a 16-bit "1" as 00000001 00000000, but you always write the bits from left to right. It's the bytes (not bits) that are right-to-left in that case. It would be unnecessarily confusing to store layermasks as little-endian, so they are always big-endian regardless of whether the processor you're using is little- or big-endian. (You do need to be aware of endianness when using something like System.IO.BinaryReader, since in that case the order of the bytes depends on the CPU, and the framework won't handle it for you.)
Now it will be easier to understand.
What is faster? Enum or Layer$$anonymous$$ask ?
Answer by Statement · Dec 07, 2009 at 09:37 AM
This is an attempt to simplify Stelimars insightful post.
LayerMask, or any "Mask" in Computer Science, is an integer which uses its 32 bits to represent different flags. While it is an integer, the value doesn't mean anything useful numerically. What matters is which flags are turned on or off.
In the case of LayerMask, each flag (each bit) represents one layer. If you select any game object from the editor you'll notice the Layer field in the top right corner of the inspector. Clicking this will bring up a list of different layers. There are some predefined Layers, but you can also add layers. Notice how you have 32 slots for your layers. This is because Unity uses an integer type to store the flags in each of the 32 bits that makes up an integer. As we can see, Layer 8 to 31 is available for us to define for our own game.
Since Masks use a single bit to represent if some option is true or false, a Mask can contain many different options. The same goes when thinking about Layers. A LayerMask specifies which Layers are enabled for any given mechanism. This enables us to tell the game that our GameObject "Don", for example, is thought to belong to the user defined layer "NPC" and "Bob" to belong to the user defined layer "SpellCaster".
Then, we make us of this information for example in a raycast call, specifying that the raycast should only return objects that belong to the "NPC" layer. An example when this could be used is when you want to target NPCs only with the click of the mouse. Then, imagine you have a game where you want to cast a spell, and that spell can only target Spell Casters. Then you'd only include the game objects that has the SpellCaster layer enabled. A third option would be to include both NPC and SpellCaster in the search. That way we would test both Don and Bob.
Finally some technical mumbo.
Technical
A LayerMask is represented as a 32bit integer. It also has a name table for naming the different bits so it is more readily understood by us game developers. Just to give some perspective, here's how a 32 bit integer would look like if it was written.
0000 0000 0000 0000 0000 0000 0000 0000
I put a space between every 4th bit to make it easier to read.
The first bit is actually located on the right side. Think of this as being the first layer. Here's how it would look if the first bit (or layer) would be set:
0000 0000 0000 0000 0000 0000 0000 0001
Since Unity predefines 8 layers, we can display the Mask for including all of those layers as such:
0000 0000 0000 0000 0000 0000 1111 1111
And if we like to search for NPC as from the example above, given we've put it in User Layer 8 (starting from 0, this is the 9th layer), we'd mask it as:
0000 0000 0000 0000 0000 0001 0000 0000 // NPC Layer
Just for completeness, this is how you should think a mask that include NPC OR SpellCaster should look like, if we assume the SpellCaster was set to User Layer 9:
0000 0000 0000 0000 0000 0011 0000 0000 // NPC | SpellCaster Layer
Example
Allright, now that you see we're setting bits to enable the different layers, let's look at how we generate the bit field from scratch using C#. In my example, I will make three masks that can be used to query NPCs, SpellCasters, and "NPCs and SpellCasters". We'll use Physics.Raycast in our example.
Example 1: Raycast vs NPCs
int NPCLayer = 8;
// This is used to illustrate which Layer we want to use.
int NPCMask = 1 << NPCLayer;
// This is used to generate the Mask derived from NPC Layer.
if Physics.Raycast(fromPosition, direction, Mathf.Infinity, NPCMask)
{
// We cast a ray onto a NPC!
}
Example 2: Raycast vs SpellCasters
int SpellCasterLayer = 9;
// This is used to illustrate which Layer we want to use.
int SpellCasterMask = 1 << SpellCasterLayer;
// This is used to generate the Mask derived from SpellCaster Layer.
if Physics.Raycast(fromPosition, direction, Mathf.Infinity, SpellCasterMask)
{
// We cast a ray onto a spell caster!
}
Example 3: Raycast vs NPCs and SpellCasters
int NPCLayer = 8;
int SpellCasterLayer = 9;
// This is used to illustrate which Layers we want to use.
int NPCMask = 1 << NPCLayer;
int SpellCasterMask = 1 << SpellCasterLayer;
// This is used to generate the Mask derived from the layers.
int CombinedMask = NPCMask | SpellCasterMask;
// We use the binary OR operator to combine masks.
if Physics.Raycast(fromPosition, direction, Mathf.Infinity, CombinedMask)
{
// We cast a ray onto a NPC or a SpellCaster!
}
Stelimar also have excellent information in his posts that you should read.
Excellent Post! Just one small point. If you are loading the layer from the string: [int NPCLayer = Layer$$anonymous$$ask.NameToLayer ("NPCLayer");] you still need to perform the mask afterwards: [int NPC$$anonymous$$ask = 1 << NPCLayer;]
The << operator is a shift operator. 1 << 8 means that you'd take the integer 1, and shift all bits 8 bits "to the left". 0 << 8 would return 0, since having an integer full of zero bits is still the same integer no matter which direction or how many bits you shift it.
If you want to make a mask that is all of the layers except layer 8, you'd do ~(1 << 8). http://msdn.microsoft.com/en-us/library/d2bd4x66.aspx
@$$anonymous$$ish:
I know this is a bit late...but I've used the following approach in the past to exclude a layer from a mask (I'm not saying it is the "right way" or even a good way, but it has worked for me in the past:
public int npcComp = 8;
public int playerComp = 9;
public int terrain = 10;
public Layer$$anonymous$$ask hittableLayers; //public just for easy display.
void Start()
{
hittableLayers = (1 << npcComp) | (1 << playerComp);
hittableLayers = hittableLayers | (1 << terrain); //'adds' terrain layer.
hittableLayers = hittableLayers ^ (1 << terrain); //'removes' terrain layer.
}
It occurs to me you could also do:
hittableLayers = hittableLayers & ~(1 << terrain); //'removes' terrain layer.
Answer by Eric5h5 · Jul 05, 2010 at 03:03 AM
While the information about layermasks in the other answers is good, it would be remiss not to mention the LayerMask type. Generally this is the easiest way to use them, since you don't have to convert anything or know anything about binary math (although it's a good idea to have that knowledge anyway, in case you want to do more complex layermask coding).
var myLayerMask : LayerMask;
if Physics.Raycast(fromPosition, direction, Mathf.Infinity, myLayerMask)
{
// Do something
}
This way you can simply choose the appropriate layers in the inspector.
Excellent information, works perfectly for general purpose. Thanks Eric!
Regarding the use of the Layer$$anonymous$$ask type, I find myself wondering how we're actually meant to use it in Physics.Raycast(). Here you use myLayer$$anonymous$$ask but the unity documentation advises the use of myLayer$$anonymous$$ask.value. Over at #unity3D @ Freenode they tell me they both achieve the same result. What's your take?
@jmpp: They're correct; it evaluates to the integer value anyway.
God damn it why the hell isn't this the first thing everyone mentions!? lol I don't wanna learrrrn all this stuffffff.
If you're trying to access a layer mask by name you use Layer$$anonymous$$ask.NameToLayer("LAYERNA$$anonymous$$E") which returns an integer. I always use it in my code since I feel more comfortable using layer names than numbers.
Here's an example
raycastLayer$$anonymous$$ask = (1 << Layer$$anonymous$$ask.NameToLayer("World Geometry")) | (1 << Layer$$anonymous$$ask.NameToLayer("Raycast Affected Triggers"));
Answer by DanSuper · Dec 14, 2012 at 08:31 PM
The answers above do a great job of explaining how to use LayerMasks and the technical stuff behind it. This is just a little additional information I thought people might find helpful.
I find that working with LayerMasks by name instead of layer number makes the process a lot cleaner to read.
The LayerMask class has static methods
int NameToLayer(string layerName) // Returns Layer Number From Layer Name
string LayerToName(int layer) // Returns Layer Name From Number
When I build LayerMasks in my scripts, I alway use the names instead of the numbers. For instance...
lightBeamLayerMask = (1 << LayerMask.NameToLayer("World Geometry"))
| (1 << LayerMask.NameToLayer("Light Triggers"));
This way I don't have to worry about whether "World Geometry" is Layer 8, or 10.
Also, I usually store LayerMasks as private variables and build them once in the Start() method, rather than creating them immediately before using them like the Unity Scripting Reference Examples.
Answer by Creator347 · Aug 06, 2013 at 01:17 PM
Although you can always use the other mentioned methods to get the perfect layer-mask you desire. I'd like to point out another possibility to have the layermask. Which is actually putting the integer hardcoded. It's not recommended though, unless you've got some problems with any other method, or may be if you've a doubt that your bitwise calculations are not correct.
For eg. if you want to include layer 2 and 4 in the layermask, the calculation should be
int mask = 1<<2 | 1<<4;
which will result into 0001 0100
which in decimal results into 20
, so you can just put 20
as a layermask too.
int mask = 20;
So instead of putting the calculation in the code, you are doing calculations yourself and putting just the result. However since it's hardcoding, I'd not recommend using this method except for debugging.
You can use online converters which can make this easier for you. For eg. - http://www.binaryhexconverter.com/binary-to-decimal-converter
Follow this Question
Related Questions
Colliders attached to objects on separate layers are colliding? 1 Answer
My LayerMask is not working 1 Answer
Ignore one layermask question 1 Answer
Select 2D Object By Mouse ? 4 Answers