Search Unity

Set LayerMask to Everything via code c#?

Discussion in 'Scripting' started by Jason-K, Apr 26, 2017.

Thread Status:
Not open for further replies.
  1. Jason-K

    Jason-K

    Joined:
    Dec 1, 2014
    Posts:
    35
    I find myself needing to create LayerMasks that are set to "Everything" fairly often in code. The easiest way I know of to do that is to manually set the value in the inspector. Is there an easy way to set a LayerMask to "Everything" in code? I would need it to work regardless of how many layers are in game so it doesn't become broken if new layers are added.

    I searched and experimented but could not find a solution. I figure there might be a simple solution I haven't found. Does anyone know of such a solution? Alternatively, does anyone know for sure that such a solution does not exist?
     
    FaffyWaffles and ciindaboss like this.
  2. mikael_juhala

    mikael_juhala

    Joined:
    Mar 9, 2015
    Posts:
    247
    Code (CSharp):
    1. mask = ~0
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Such a solution definitely exists, if you're aware that a LayerMask is just a series of bits. I mean, obviously everything on your computer is, but the LayerMask is actually used as such: each bit represents a layer that is either on or off. Under the hood it's represent as an int, and can be easily asssigned as such.

    So the question is: what value of an int is all 1's in binary? You could google that, and you'd get a number which you could plug in (you want the result of 2^32 - 1) and it'd work. But we can do this in a slightly cleaner way, using a bitwise NOT operator, which in C# is tilde (~) - which will literally reverse every bit in a value. So now the question is, what int value is all 0's in binary?

    Spoiler: it's 0.
    Code (csharp):
    1. LayerMask someMask = ~0;
    edit: beaten to it by someone who just had to type the answer. ;) Well, now you know how that answer was arrived at.
     
    leative, dimicode, Genebris and 32 others like this.
  4. Jason-K

    Jason-K

    Joined:
    Dec 1, 2014
    Posts:
    35
  5. merlin4

    merlin4

    Joined:
    Jan 24, 2015
    Posts:
    3
    LayerMask everything = -1;

    This works thanks to twos-complement representation.
     
  6. eblavender

    eblavender

    Joined:
    Sep 4, 2017
    Posts:
    14
    What about setting the layer mask to "Nothing"?
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    Each bit is a layer obviously so that would mean no bits set (zero).
     
    Bunny83 likes this.
  8. Eppu_Benjamin

    Eppu_Benjamin

    Joined:
    Jan 9, 2017
    Posts:
    2
    For anyone wandering into here, bit operations are a powerful and very fast way to handle masks.
    You can have

    Code (CSharp):
    1. int layer1 = 1;       // ..0001 as bits, 1 as a number
    2. int layer2 = 1 << 2;  // ..0010 as bits, 2 as a number
    3. int layer3 = 1 << 3;  // ..0100 as bits, 4 as a number
    4. int layer4 = 1 << 4;  // ..1000 as buts, 8 as a number
    Then you compare them with AND, OR and other operators.

    Code (CSharp):
    1. int res1 = layer1 & layer2  // ..0011 as bits, 3 as a number (2+1)
    2. int res2 = layer1 & layer3  // ..0101 as bits, 5 as a number (4+1)
    3.  
    4. if (1 << gameObject.layer & layer1) > 0)
    5. {
    6.   // do stuff
    7. }
    The above if-statement compares two layers to each other, and if they are the same (have the on-bit in the same place) it returns true because the resulting int has all bits on that are on in both. The fact that gameObject.layer is an int representing the number of the layer in the layer list complicates it a little, but not much. To get that as a bit, just do the 1 << layer operation to get it as bit representation.

    https://mathiassoeholm.github.io/Layer-Masks-In-Depth/ <- nice explanation of how bit flagging works.

    You could also build preset masks with the OR operator:

    Code (CSharp):
    1. public static class Layers
    2. {
    3.     public const int Character = 1 << 6;
    4.     public const int Destructible = 1 << 7;
    5.     public const int Indestructible = 1 << 8;
    6.     public const int ProjectileHits = Character | Destructible | Indestructible;
    7. }
     
    Last edited: Mar 26, 2022
    Jellezilla, Matsyir and jeremedia like this.
  9. JonnyD

    JonnyD

    Joined:
    Feb 23, 2016
    Posts:
    1
    Also, `Physics.AllLayers` exists.
     
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    fnnbrr and Bunny83 like this.
  11. BurningthumbStudios

    BurningthumbStudios

    Joined:
    Apr 28, 2008
    Posts:
    95
    Its a problem because LayerMask is an int, which is signed meaning you can't normally just set bits without using negative values because the language syntax processor is checking to make sure you don't make an error.

    But, if you know what you are doing, you can just use an unchecked syntax that and it will let you set the bits, like so:

    Code (CSharp):
    1. [SerializeField] LayerMask m_myLayerMask = unchecked((int)0xffffffff);
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    MelvMay likes this.
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    That's what Bitwise/Shift operators on int, uint, long and ulong are for. There should be no need to use unchecked in this case.

    https://learn.microsoft.com/en-us/d...ference/operators/bitwise-and-shift-operators

    As Kurt points out with an example being here: https://github.com/Unity-Technologi...hysics/ScriptBindings/Physics.bindings.cs#L89
     
Thread Status:
Not open for further replies.