- Home /
Using a bitwise operator with LayerMask
(I searched all over for this and couldn't find a simple Q&A)
I'm trying to test if a GameObject.layer is in a LayerMask.value. e.g.:
if ((layerMask.value & hitObject.layer) == hitObject.layer)
Debug.Log(hitObject.name + " is in one of our layers");
When I Debug.Log the test expression, it always prints 0. When try Debug.Log a simple test, such as 3 & 2, it prints 2.
Any Idea why this comparison isn't working?
(this.layers.value & hitObject.layer)
As a secondary question, could I just test to see if the return is > 0 to avoid a second look-up?
I like your function. So I made it a bit more compact and put it on a Tools class.
using UnityEngine;
public class Tools {
public static bool IsInLayer$$anonymous$$ask(GameObject obj, Layer$$anonymous$$ask mask){
return ((mask.value & (1 << obj.layer)) > 0);
}
}
That way you can just access it from anywhere just by doing:
Tools.IsInLayer$$anonymous$$ask(myGameObject, myLayer$$anonymous$$ask);
Answer by Rafes · Jul 30, 2011 at 08:26 PM
There is a great explanation here that I hadn't considered: http://answers.unity3d.com/questions/122586/layermask-vs-1ltlt-gameobjectlayer-.html
I need to 'cast' the object's layer, which is the integer shown in the inspector, in to the masked version, which is used to compare with the LayerMask. For example, layer "6" in 1, 2, 3, 4, 5, 6 needs to be 1, 2, 4, 8, 16, 32
Here is a working function to do this:
/// <summary>
/// Checks if a GameObject is in a LayerMask
/// </summary>
/// <param name="obj">GameObject to test</param>
/// <param name="layerMask">LayerMask with all the layers to test against</param>
/// <returns>True if in any of the layers in the LayerMask</returns>
private bool IsInLayerMask(GameObject obj, LayerMask layerMask)
{
// Convert the object's layer to a bitfield for comparison
int objLayerMask = (1 << obj.layer);
if ((layerMask.value & objLayerMask) > 0) // Extra round brackets required!
return true;
else
return false;
}
For a small improvement ins$$anonymous$$d:
if ((layer$$anonymous$$ask.value & objLayer$$anonymous$$ask) > 0) // Extra round brackets required!
return true;
else
return false;
simply
return ((layer$$anonymous$$ask.value & objLayer$$anonymous$$ask) > 0)
Right, most people don't seem to realise what a boolean value actually is. Though the outer brackets aren't needed.
return (layer$$anonymous$$ask.value & objLayer$$anonymous$$ask) > 0;
Answer by AlexanderPatrick · Aug 25, 2014 at 04:28 AM
I learned about extension methods recently and thought I would contribute to this as well.
namespace ExtensionMethods {
public static class LayerMaskExtensions {
public static bool IsInLayerMask(this LayerMask mask, int layer) {
return ((mask.value & (1 << layer)) > 0);
}
public static bool IsInLayerMask(this LayerMask mask, GameObject obj) {
return ((mask.value & (1 << obj.layer)) > 0);
}
}
}
Which can then be used like this:
using UnityEngine;
using ExtensionMethods;
public class LayerMaskTest : MonoBehaviour {
public LayerMask layerMask;
void OnTriggerEnter2D(Collider2D hitObject) {
if ( layerMask.IsInLayerMask(hitObject.gameObject) ) {
Debug.Log(hitObject.name + " is in one of our layers");
}
}
}
I like your idea but I tried and I ended in use a class ins$$anonymous$$d of the namespace. I don't why I am very new with C#.
Your answer
Follow this Question
Related Questions
Layermask (raycast) wont work... 4 Answers
Detecting that I'm clicking a unit even though I'm not? 0 Answers
LayerMask for RayCast 1 Answer
Return Objects hit by raycast, check against a array of all objects? 1 Answer
How to make my raycast also hit deactive objects WITHOUT showing the object? 1 Answer