Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question LayerMask with multiple defaults

Discussion in 'Scripting' started by Lala_Ghost, Jun 27, 2023.

  1. Lala_Ghost

    Lala_Ghost

    Joined:
    Jun 18, 2017
    Posts:
    7
    I am trying to give my layerMask multiple default values with a bitwise operator but it does not work.

    When I type this:
    Code (CSharp):
    1. [SerializeField] private LayerMask _layerMask = 1 << 1;
    Only the TransparentFX is selected on the gameObject with this script attached.

    When I type this:
    Code (CSharp):
    1. [SerializeField] private LayerMask _layerMask = 1 << 2;
    Only the Ignore Raycast is selected on the gameObject with this script attached.

    Thats why I tried this:
    Code (CSharp):
    1. [SerializeField] private LayerMask _layerMask = 1 << 1 & 2;
    But this selects only the TransparentFX, too.
    How do I have to define my layerMask so that I can assign multiple layers to it by default?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    I should point out that:
    1 << 1 == 10binary == 2decimal

    So that last one is just saying:
    2 & 2
    which equals... 2

    What I do for my masks is I create a constants class for all my known layers and masks:
    Code (csharp):
    1.     public static class Constants
    2.     {
    3.  
    4.         public const string TAG_PLAYER = "Player";
    5.  
    6.         public const int LAYER_PATHING = 3;
    7.         public const int LAYER_TERRAIN = 24;
    8.         public const int LAYER_OBSTACLE = 25;
    9.  
    10.         public const int MASK_PATHING = 1 << LAYER_PATHING;
    11.         public const int MASK_TERRAIN = 1 << LAYER_TERRAIN;
    12.         public const int MASK_OBSTACLE = 1 << LAYER_OBSTACLE;
    13.  
    14.     }
    Here's a quick example with a handful of layers.

    Then in your code you can do:
    Code (csharp):
    1. [SerializeField] private LayerMask _layerMask = Constants.MASK_TERRAIN | Constants.MASK_OBSTACLE;
    If you wanted to inline that:
    Code (csharp):
    1. [SerializeField] private LayerMask _layerMask = (1 << 24) | (1 << 25);
    Note that I use the | (or) operator to combine the masks.

    My constants will even get versions of the combined masks at times:
    Code (csharp):
    1.     public static class Constants
    2.     {
    3.  
    4.         public const string SCENE_PRECINCTLOBBY = "PrecinctLobby";
    5.         public const string SCENE_MAINMENU = "MainMenu";
    6.  
    7.         public const string TAG_GAMEPLAYCAMERA = com.mansion.SceneGenerator.CameraZone.TAG_GAMEPLAYCAMERA;
    8.  
    9.         public const string GO_CAMLOOKATGOAL = "CameraGoalLookAt";
    10.  
    11.         public const string ANIMEVENT_RELEASETHROW = "ReleaseThrow"; //signaled by the 'throw' anim to let the player know to release the object it's throwing, if left out the end of 'throw' will act as this
    12.         public const string ANIMEVENT_FIREPROJECTILE = "FireProjectile"; //signaled by the 'aimFire' anim to let the player know to actually fire the shot, if left out the end of 'aimFire' will act as this
    13.  
    14.         //public const float GRAV_STRENGTH = 9.8f;
    15.         public const float GROUND_Y = 0f;
    16.         public const float DEFAULT_CAMERAOFFSETANGLE = -30f;
    17.  
    18.         public const int LAYER_DEFAULT = 0;
    19.         public const int LAYER_ENTITYEVT = 8;
    20.         public const int LAYER_PLAYER = 9;
    21.         public const int LAYER_ENEMY = 10;
    22.         public const int LAYER_NPC = 11;
    23.         public const int LAYER_ITEM = 12;
    24.         public const int LAYER_FLOOR = 24;
    25.  
    26.         public const int MASK_DEFAULT = 1 << LAYER_DEFAULT;
    27.         public const int MASK_ENTITYEVT = 1 << LAYER_ENTITYEVT;
    28.         public const int MASK_PLAYER = 1 << LAYER_PLAYER;
    29.         public const int MASK_ENEMY = 1 << LAYER_ENEMY;
    30.         public const int MASK_NPC = 1 << LAYER_NPC;
    31.         public const int MASK_ITEM = 1 << LAYER_ITEM;
    32.         public const int MASK_FLOOR = 1 << LAYER_FLOOR;
    33.  
    34.         public const int MASK_ENTITY = MASK_PLAYER | MASK_ENEMY | MASK_NPC | MASK_ITEM;
    35.         public const int MASK_MOBILEENTITY = MASK_PLAYER | MASK_ENEMY | MASK_NPC;
    36.         public const int MASK_SHOOTABLE = MASK_DEFAULT | MASK_PLAYER | MASK_ENEMY | MASK_NPC | MASK_FLOOR;
    37.  
    38.     }
    Note MASK_ENTITY and MASK_SHOOTABLE at the end there.
     
    Last edited: Jun 27, 2023
    Bunny83, Kurt-Dekker and CodeRonnie like this.
  3. CodeRonnie

    CodeRonnie

    Joined:
    Oct 2, 2015
    Posts:
    280
    lordofduct already provided good examples of combining bit flags for bit masking. Here are some examples of directly manipluating the LayerMask variable.
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class Foo : MonoBehaviour
    5. {
    6.     [SerializeField]
    7.     private LayerMask LayerMask;
    8.  
    9.  
    10.     public void EnableLayerMask(int layerMask)
    11.     {
    12.         LayerMask |= layerMask;
    13.     }
    14.  
    15.     public void DisableLayerMask(int layerMask)
    16.     {
    17.         LayerMask &= ~layerMask;
    18.     }
    19.  
    20.  
    21.     public void EnableLayer(string layerName)
    22.     {
    23.         if(TryGetLayerMask(layerName, out int layerMask))
    24.             EnableLayerMask(layerMask);
    25.     }
    26.  
    27.     public void DisableLayer(string layerName)
    28.     {
    29.         if(TryGetLayerMask(layerName, out int layerMask))
    30.             DisableLayerMask(layerMask);
    31.     }
    32.  
    33.     public void EnableLayers(string[] layerNames)
    34.     {
    35.         if(TryGetLayerMask(layerNames, out int layerMask))
    36.             EnableLayerMask(layerMask);
    37.     }
    38.  
    39.     public void DisableLayers(string[] layerNames)
    40.     {
    41.         if(TryGetLayerMask(layerNames, out int layerMask))
    42.             DisableLayerMask(layerMask);
    43.     }
    44.  
    45.  
    46.     private readonly string[] LayerNames = new string[1];
    47.  
    48.     public void EnableLayerAlt(string layerName)
    49.     {
    50.         LayerNames[0] = layerName;
    51.         if(TryGetLayerMask(LayerNames, out int layerMask))
    52.             EnableLayerMask(layerMask);
    53.     }
    54.  
    55.     public void DisableLayerAlt(string layerName)
    56.     {
    57.         LayerNames[0] = layerName;
    58.         if(TryGetLayerMask(LayerNames, out int layerMask))
    59.             DisableLayerMask(layerMask);
    60.     }
    61.  
    62.  
    63.     public static bool TryGetLayerMask(string layerName, out int layerMask)
    64.     {
    65.         layerMask = 0;
    66.         int layerNumber = LayerMask.NameToLayer(layerName);
    67.         if(layerNumber == -1)
    68.         {
    69.             Debug.LogWarning($"Invalid layer name: {layerName}");
    70.             return false;
    71.         }
    72.         // LayerMask.NameToLayer returns the consecutive numerical order of a layer in the layer list. It needs to be converted into a bit flag.
    73.         layerMask = 1 << layerNumber;
    74.         return true;
    75.     }
    76.  
    77.     public static bool TryGetLayerMask(string[] layerNames, out int layerMask)
    78.     {
    79.         // NOTE: Unity handles what happens if you have a mixture of invalid layer names here.
    80.         layerMask = LayerMask.GetMask(layerNames);
    81.         if(layerMask == 0)
    82.         {
    83.             Debug.LogWarning($"Invalid layer name array.");
    84.             return false;
    85.         }
    86.         return true;
    87.     }
    88. }
    89.  
     
    Last edited: Jun 27, 2023
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    I'm even lazier, but in a good way.

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. // @kurtdekker - part of Jetpack Kurt Space Flight
    4.  
    5. public static class MyLayers
    6. {
    7. // Jetpack Kurt stuff:
    8.     public const string s_NoShadow = "noshadow";
    9.     public const string s_Player = "player";
    10.     public static int i_Player { get { return LayerMask.NameToLayer (s_Player); } }
    11.     public static int MaskNotPlayer { get { return ~(1 << i_Player); } }
    12.     public const string s_Shots = "shots";
    13.     public static int i_Shots { get { return LayerMask.NameToLayer (s_Shots); } }
    14.     public const string s_Aliens = "aliens";
    15.     public const string s_Bombs = "bombs";
    16.     public const string s_Static = "static";
    17.     public const string s_Motes = "motes";
    18.     public const string s_Markers = "markers";
    19.     public static int i_Markers { get { return LayerMask.NameToLayer (s_Markers); } }
    20.  
    21. // Utility:
    22.     public static void SetLayerRecursively( GameObject go, int layer)
    23.     {
    24.         go.layer = layer;
    25.         foreach( Transform tr in go.transform)
    26.         {
    27.             SetLayerRecursively( tr.gameObject, layer);
    28.         }
    29.     }
    30.  
    31.     public static void SetLayerRecursively( GameObject go, string layerName)
    32.     {
    33.         SetLayerRecursively (go, LayerMask.NameToLayer (layerName));
    34.     }
    35. }
     
    CodeRonnie likes this.
  5. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Here's my crash course on bitwise operators, layer masks, and flags.
     
    Bunny83 likes this.