Right, I guess Kurt had something mixed up when he wrote his answer back then. Because he explained it the other way round
Yes, a mask is masking layers which you want / don’t want to hit. Though a 1 in the mask means you can hit the layer, a 0 at the corresponding bit position means you can not hit that layer. So a mask of “0” would mean you can’t hit anything while “-1” (equivalent to 0xFFFFFFFF) means all 32 layers can be hit, even the “ignore raycast layer” which is usually excluded in the Physics.DefaultRaycastLayers ^^.
Just to make that clear again. We already have countless of other posts that explain this, but I think there’s always someone that finds this thread before any other, so it doesn’t hurt.
A 32 bit integer, as the name suggests, has 32 bits. A bit can either be set (so it’s 1) or clear (so the bit is 0). To visualize a bit mask, we can write the number as a binary number like that
1111 1111 1111 1111 1111 1111 1111 1011
The default layer masks are defined here. The binary number I just showed is the actual value of “DefaultRaycastLayers”. So all 32 bits are set, except bit number 2 (the third layer since we start counting at 0) which represents the ignore raycast layer.
When you would use the decimal number “9” as a layermask, you would actually use a mask like this:
0000 0000 0000 0000 0000 0000 0000 1001
which is binary for “9” is only includes layer 0 and layer 3. Layer 0 has the value 1 (== 1 << 0) while layer 3 has the value 8 (== 1 << 3). With the “bitshift left” operator you can easily get the actual mask value for a certain layer since the bit shift simply shifts the bits in the given number by x bits to the left. So by using the number 1 and shifting it x times to the left, you get the value for only layer x.
While you could simply “add” several layer mask values up (1 + 8 == 9) it is not recommended as when you try to combine two layer masks that have “overlaps”, you get a “carry” and it results in the wrong bits being set. To combine several bitmasks into one, you should use bitwise operators like or |
, and &
as well as not ~
Just as an example, imagine the layermasks “33” (0010 0001, so layer 0 and layer 5) and the layermask 3 (0000 0011, so layer 0 and layer 1). When you just “add” them up (33 + 3 == 36) you get a mask that looks like this: 0010 0100. So we would get layer 5 and layer 2. Though our two initial masks contained layer 0 and 1. When using the proper bitwise or operator, each bit is "or"ed with the corresponding bits. So doing 33 | 3 == 35
0010 0001 (33)
0000 0011 ( 3)
---------
0010 0011 (35)
The bitwise “not” operator ~
simply inverts all bits. So every bit that was originally 0 becomes a 1 and every 1 becomes a 0. So a mask like 0000 0000 0000 0001 0000 0100 0010 0011
( == 1+2+32+1024+65536 == 66595), when you invert it it becomes 1111 1111 1111 1110 1111 1011 1101 1100
(== 4294900700 as an unsigned integer)
For those not familiar with the binary system, if you’re on a windows system you can start up the built-in calculator (calc.exe) and switch it to programmer mode. It allows you to view numbers as hexadecimal (base 16), decimal (our usual base 10 system), octal (base 8) or binary (base 2). All those number systems actually work exactly the same, though they have different number of symbols per digit. That changes the “value” of a certain digit position. While in the decimal system each digit place is the value of the previous place multiplied by 10 (so “ones” at the far right, then 10s, 100s, 1000s, …), in binary each digit grows by a factor of 2. So we have ones then 2s, 4s, 8s, 16s, 32s, 64s, 128s, …
When you count in a number system you generally start at the ones place and go through the available digits. For decimal thats 0 through 9. When you add another one you get a carry into the 10s place and the ones go back to 0. In the binary system the only available digits are 0 and 1. So once we have a 1 in the ones place and we add one, we get a carry into the 2s place and the ones place goes back to 0. So we get "10"b.
Counting up from 0 to 20 in binary, oct, dec, hex
BIN DEC binary composition HEX OCT
----------------------------------------------------
0000 0000 ( 0) [ ] 0x00 000
0000 0001 ( 1) [ 1 ] 0x01 001
0000 0010 ( 2) [ 2 ] 0x02 002
0000 0011 ( 3) [ 2 + 1 ] 0x03 003
0000 0100 ( 4) [ 4 ] 0x04 004
0000 0101 ( 5) [ 4 + 1 ] 0x05 005
0000 0110 ( 6) [ 4 + 2 ] 0x06 006
0000 0111 ( 7) [ 4 + 2 + 1 ] 0x07 007
0000 1000 ( 8) [ 8 ] 0x08 010
0000 1001 ( 9) [ 8 + 1 ] 0x09 011
0000 1010 (10) [ 8 + 2 ] 0x0A 012
0000 1011 (11) [ 8 + 2 + 1 ] 0x0B 013
0000 1100 (12) [ 8 + 4 ] 0x0C 014
0000 1101 (13) [ 8 + 4 + 1 ] 0x0D 015
0000 1110 (14) [ 8 + 4 + 2 ] 0x0E 016
0000 1111 (15) [ 8 + 4 + 2 + 1 ] 0x0F 017
0001 0000 (16) [ 16 ] 0x10 020
0001 0001 (17) [ 16 + 1 ] 0x11 021
0001 0010 (18) [ 16 + 2 ] 0x12 022
0001 0011 (19) [ 16 + 2 + 1 ] 0x13 023
0001 0100 (20) [ 16 + 4 ] 0x14 024
.........
Looking at that table you will see why we often use hexadecimal numbers instead of binary. They have a neat 4-to-1 relationship (every 4 binary digits make up a single hex digit). So it’s easy to do a (partial) conversion between the two systems.