2
\$\begingroup\$

I'm experimenting with 2d physics, and the problem is this: The IsTouchingLayers function reveals that the object is touching a layer, but only if I use the-1 parameter which is equivalent to Physics2D.AllLayers.

These are the tests done on Visual Studio in debug in the immediate control window:

?Physics2D.AllLayers
-1

?GroundCheck.IsTouchingLayers(-1)
true

?GroundCheck.IsTouchingLayers(0)
false
?GroundCheck.IsTouchingLayers(1)
false
?GroundCheck.IsTouchingLayers(2)
false
?GroundCheck.IsTouchingLayers(3)
false
?GroundCheck.IsTouchingLayers(4)
false
?GroundCheck.IsTouchingLayers(5)
false
?GroundCheck.IsTouchingLayers(6)
false
?GroundCheck.IsTouchingLayers(7)
false
?GroundCheck.IsTouchingLayers(8)
false
?GroundCheck.IsTouchingLayers(9)
false
?GroundCheck.IsTouchingLayers(10)
false
?GroundCheck.IsTouchingLayers(11)
false
?GroundCheck.IsTouchingLayers(12)
false
?GroundCheck.IsTouchingLayers(13)
false
?GroundCheck.IsTouchingLayers(14)
false
?GroundCheck.IsTouchingLayers(15)
false
?GroundCheck.IsTouchingLayers(16)
false
?GroundCheck.IsTouchingLayers(17)
false

These are the layers I have in the project:

enter image description here

If I use the -1 parameter it works correctly, the character jumps when it touches the ground and does not jump when it is in the air, but it will definitely jump by touching any layers. And anyway I want to understand why.

What am I doing wrong ?

Thank you

\$\endgroup\$
4
\$\begingroup\$

I think it is a problem of misunderstanding, and lack of good documentation from Unity's side, of how the Layers are represented on Editor and how their values really are. If you read IsTouchingLayer's documentation, you can see that just by mere semantics the int you have to provide is that of a layer mask. LayerMasks make use of a technique called bit-masking, which is a technique used to store many flags into a chain of bits, for optimization purposes. So, for example, being an integer a 4 bytes (32 bits) type, you can store up to 32 flags (saving you the need to potentially declare up to 32 bools, for example).

So, if you consulted the links I provided and understood the basics of bit-masking, we can now understand more clearly why the Layers presented on editor are between 0 and 32:

  • Layer 0 (Default) = 1 << 0 = 1
  • Layer 1 (TransparentFX) = 1 << 1 = 2
  • Layer 2 (IgnoreRaycast) = 1 << 2 = 4
  • ...
  • Layer 32 (CustomLayer) = 1 << 32 = 2,147,483,647
  • So basically: Layer N (CustomLayer) = 1 << N = 2 raised to the N

So what you must pass are the numbers of the Layers but using bit shifting (so for example, if you wanted to pass the layer 4, you can either pass it as 1 << 4 or 16). And you can also pass multiple layer values, say you want to pass layers 4, 5 and 7:

int layerMask = (1 << 4) | (1 << 5) | (1 << 7)

And that is why the use of an exposed (public or serializable) LayerMask, instead of you yourself doing bit shifting operations, is sometimes the way to go, it does things more easily. So you could do instead:

public class Example : MonoBehaviour
{
    public LayerMask layerMask;
    public Collider2D ground;

    private void Awake()
    { /// LayerMask has an implicit conversion to int
        Debug.Log(ground.IsTouchingLayers(layerMask));
    }
}

Hope it helps.

\$\endgroup\$
  • \$\begingroup\$ I feel like letting int implicitly cast to LayerMask was a mistake that's caused a lot of easily avoidable errors. :( Much better to require the user to use a method that makes it explicit whether they're providing a layer index or a bitmask, so it can apply the appropriate transformations automatically and be obvious about what it's doing. \$\endgroup\$ – DMGregory Apr 24 at 23:02
  • \$\begingroup\$ Thanks a lot! You are right. In fact passing the LayerMask Map it works. Checking the value of Map (the layer number 9) is 512, so 1 << 9 = 512. Thank you very much. \$\endgroup\$ – Baro Apr 25 at 8:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.