I don’t pass a layerMask, but "Ignore Raycast" is not ignored

I’m having some weird raycast problem.

Documentation says “When you don’t pass a layerMask to the Raycast function, it will only ignore colliders that use the IgnoreRaycast layer.” But:

Even if I pass the mask ~(1<<2), it will still hit gameobjects

Try printing raycastHit.collider.gameObject.layer instead of what you are printing now.

The problem could be that you have the collider on a different layer, and the transform field of the RayCastHit will return the Transform of the parent Rigidbody if one exists, which may not have the same layer as the collider itself.

1 Like

The layerMask is what you can HIT. If you want to only check vs. layer 7, use 1<<7. To check vs. layers 7 and 11 use (1<<7 | 1<<11). In your example, ~(1<<2) is 11111111111101, which means you can hit any layer except 2. The way layerMask is explained is part of the problem: “a layerMask allows you to ignore things”, but it does that by leaving them out of the list. It’s sort of like saying a Guest List allows you to keep certain people out of the party.

The IgnoreRaycast layer is a hack to be nice to beginners. I assume a layerless raycast automatically uses ~(1<<2) for the layermask. Clever, right? Layer-2 is only special since it’s hard-coded into the default parameters. Of course, once you start making your own layers, that’s done and 2 isn’t special any more.

1 Like

Luckily we don’t have to guess. This is how the DefaultRaycastLayers constant is defined. Likewise all the Raycast variants that do not have a layermask, actually use this constant.

Though I’d like to add that using ~(1 << 2) or no layermask at all should have the same effect. So it might be the issue that @PraetorBlue mentioned above. The transform reference may reference the rigidbody instead of the collider you hit.

Now that I’m squinting to read the pictures of the code, I think the OP’s “still hitting game objects” text is misleading and PreatorBlue has it right.

I think the OP has a standard unity compound collider:

chair: ridgidBody (no collider) layer=2
  leg1: collider (no rigidBody) layer=0 [opps! This layer is wrong]
  leg2: collider (no rigidBody) layer=0 [ditto]
  ...

A raycast will hit one of the children, but you rarely care which one – you only want to know it hit the chair. so raycastHit.transform is set-up to give the rigidbody parent of what you hit. The raycast is hitting a leg (which is safely on layer 0), but the code is asking for the chair parent. PraetorBlue asking for raycastHit.collider will probably show a leg which is set to the Default layer, then side-by-side the OP can verify dot-transform and dot-collider give different results.

This is why when you change a layer on something Unity now asks “change all children”? Because the layer of the parent probably doesn’t even matter (since it usually has no collider). You really want to set the layer for all of the collider children.

3 Likes

Thanks, it helped. I just wanted to get the object that was actually hit.