# Why do Unity layer masks need to use bit shifting?

I've finally figured out why my layer masks for my ground collision code weren't working. I was using NameToLayer() to get the layer I needed, but layer masks use bit shifting to actually set the layer mask value. This is extremely unusual and I don't see any reason why this isn't handled in the code behind. Why do we have to use code like this:

mask = 1 << LayerMask.NameToLayer("Default");


when something like this:

mask = LayerMask.NameToLayer("Default");


makes more intuitive sense and works similar to the rest of the Unity API?

• Using the string version takes more processing power. Not to mention the string is internally an array which is a reference type and gets added to the garbage collector. – Krythic Oct 27 '16 at 10:54

This is extremely performant. That's all there is to it - comparing strings as the obvious example is slower by a factor of 10. And physics calculations have to be very optimized, so it's good that someone who knew what's going on wrote it this way.

So the obvious follow-up question is - why isn't this wrapped in a helper method to handle the conversion and bit-shifting. I think that no one actually got to it - I've rolled up my own nifty helper utility and that is the common practice.

• The correct design choice by the Unity team would have been to use an integer as an indexer, instead of a string. I cringe when I think about how crazy the garbage collector is likely going with their current implementation, not to mention the string array allocations. – Krythic Oct 28 '16 at 3:35
• Absolutely - any array is best referenced by integers. Integers could easily become humanly readable by a simple enum. – Jordan Georgiev Oct 28 '16 at 13:40
• A quick and dirty implementation works, but for bigger projects I use [Type Safe] (assetstore.unity3d.com/en/#!/content/35903). – Jordan Georgiev Oct 28 '16 at 13:41

Using bit shifting allows you to take into account multiple layers in one physics operation:

 Physics.Raycast(ray, out hitInfo, Mathf.Infinity, layerMask )


Without bit shifting, you would be allowed to raycast in one layer and only one. While with bit shifting, you can raycast in multiple specific layers:

layerMask = (1 << LayerMask.NameToLayer("MyLayer1")) | (1 << LayerMask.NameToLayer("MyLayer2")) ;


You can also raycast in every layers except specific ones :

layerMask = (1 << LayerMask.NameToLayer("MyLayer1")) | (1 << LayerMask.NameToLayer("MyLayer2")) ;


EDIT : I've never seen it before, but the LayerMask class has a utility function to get the "computed" layer mask given the layers names :

Debug.Log( LayerMask.GetMask("UserLayerA", "UserLayerB") ) ;


Suppose UserLayerA and UserLayerB are the tenth and eleventh layers. These will have a User Layer values of 10 and 11. To obtain their layer mask value their names can be passed into GetMask. The argument can either be a list of their names or an array of strings storing their names. In this case the return value will be 2^10 + 2^11 = 3072.

• You should use bitwise OR | instead of integer addition + when making union of masks, integer addition might produce unexpected behavior. – wondra Oct 27 '16 at 11:20
• But then again, they could have done that internally and provided a method like LayerMask.NamesToLayers(params string[] layerNames) – QBrute Oct 27 '16 at 12:11