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

Resolved Initialize LayerMask method doesn't work

Discussion in 'Scripting' started by Quasar47, Nov 14, 2020.

  1. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    117
    Hello everyone, I've written an extension class to help me initialize LayerMasks on startup. The problem is, when I do this, it's perfectly fine :

    Code (CSharp):
    1.  LayerMask whatIsGround;
    2.   void Start()
    3.     {
    4.  
    5.         if (whatIsGround.value == 0)
    6.         {
    7.             whatIsGround = 1 << LayerMask.GetMask("Ground", "GravitySurface");
    8.             whatIsGround = ~whatIsGround;
    9.         }
    10.  
    11.  
    12.     }
    But when I do this, the New() method doesn't work ?

    Code (CSharp):
    1. LayerMask whatIsGround;
    2.   void Start()
    3.     {
    4.         if (whatIsGround.Null()) whatIsGround.New("Ground", "GravitySurface");
    5.  
    6.      }
    7.  
    8.  
    9. namespace Utilities
    10. {
    11.     public static class LayerMasks
    12.     {
    13.        
    14.         public static bool Null(this LayerMask mask)
    15.         {
    16.             return mask.value == 0;
    17.         }
    18.  
    19.  
    20.         public static LayerMask New(this LayerMask mask, params string[] layers)
    21.         {
    22.             mask = 1 << LayerMask.GetMask(layers);
    23.             mask = ~mask;
    24.             return mask;
    25.         }
    26.     }

    I've called the namespace with the using keyword, the compiler doesn't throw any errors and the Null() method is correctly checked. So why does my LayerMask not register these new Layers and stays with the default "Nothing" layer ?
     
  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,051
    LayerMask
    is a value type and gets copied instead of referenced. So your
    New
    method gets a copy of the mask value, changes it, returns a changed copy, but then your code in
    Start
    discards the returned value. The original
    whatIsGround
    field is never changed.

    You need to assign the return value to copy the changes back to the field:
    Code (CSharp):
    1. if (whatIsGround.Null()) whatIsGround = whatIsGround.New("Ground", "GravitySurface");
     
    Quasar47 likes this.
  3. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    117
    Thank you, I was scratching my head for two hours now. I thought the "this" keyword allowed me to do just that but apparently it's just a shortcut, so I'll remove it.

    Edit : Just checked my values in the inspector, it turns out that this operation returned a LayerMask with all layers active except "Nothing", "Everything" and "Default", instead of just returning the layers I passed as parameters. What could that come from?
     
  4. Quasar47

    Quasar47

    Joined:
    Mar 24, 2017
    Posts:
    117
    Ok, nevermind, I found a workaroung for creating a new Layermask :

    Code (CSharp):
    1.  
    2.         public static LayerMask New(params string[] layers)
    3.         {
    4.             LayerMask mask = new LayerMask();
    5.             mask = mask.Add(layers);
    6.             return mask;
    7.         }
    8.  
    9.  
    10.         public static LayerMask Add(this LayerMask mask, params string[] layers)
    11.         {
    12.             for (int i = 0; i < layers.Length; i++)
    13.             {
    14.                 if (!mask.Contains(LayerMask.NameToLayer(layers[i])))
    15.                     mask |= 1 << LayerMask.NameToLayer(layers[i]);
    16.             }
    17.             return mask;
    18.         }
    19.  
    20.