Hi all,
I thought this would be simple, I want to do an OverlapBox collision query where CollidesWith must have both of two collision layers assigned and BelongsTo is just one collision layer. I thought I could do this:
To set two possible layers in a layermask, you would want OR, not AND.
(uint)CollisionLayers.PrimaryStaticNode```
When Unity wants to see if an object is applicable to a layermask, it checks:
```bool collisionPossible = ((1 << objectsLayerIndex) & layerMask) != 0;```
OR is not what I’m looking for though, I only want my box to collide with entities who’s physics shape belongs to both layermasks, not either or. I’ve tried using or and using + and neither gives the behavior I’m looking for.
Even if objectsLayerIndex includes all layers the object belongs to, I can’t think of any bit manipulation for layerMask that will make this true only when objectsLayerIndex includes all layers in layerMask. I’m going to try just doing multiple casts and comparing my queries but if anyone has any better suggestions please let me know!
I think you’re mixing layer indices with layer masks.
By default every collider has a single layer index from 0 to 31, and can only reside on a single layer. Let’s say your collider is on layer 13, the layer index is 13 and the smallest layer mask including it is bit 13, calculated as (1 << 13) or written as 0b0010_0000_0000_0000 or seen as an integer as 8192.
Through the use of CollisionFilters, you can say a collider effectively belongs to more than one layer. You combine multiple layer indices with (1 << indexA) | (1 << indexB) and you now have a layer mask containing the union of all mentioned indices.
The BelongsTo argument here is a layer mask.
The CollidesWith argument here is also a layer mask.
When checking the collision filtering, Unity does this by finding the intersection of two layer masks. Unity just does if ((my.BelongsTo & their.CollidesWith) != 0) and the inverse. If both masks have nonzero results, it’s a collision. It cannot determine more than nonzero like “all bits,” it’s either zero or nonzero.
I don’t see a path to have Unity Physics learn your rule “if all of the BelongsTo nonzero bits are also nonzero in CollidesWith”. The notional source code for a collision check is included on this page, and you’ll note that the function to check it is static and not virtual, and CollisionFilter is a struct anyway, so you can’t even extend to override this behavior. Anyone is welcome to prove me wrong, I still see the docs saying “the default filter” here and there but I assume it just means the default CollisionFilter value aka CollisionFilter.Default.
Thanks for the explanation. Yeah I wish there was a CollisionFilter where it could check if
if ((my.BelongsTo & their.CollidesWith) == my.BelongsTo)
I tried to find where the code is and see if I could just add some functionality myself, but didn’t have any luck, maybe for the reasons you listed. The solution I’ve found is to do the CollisionFilter with all layers I want OR’d, then iterate over all hits and check if it belongs to all layers, I just wish there were a better solution because this could potentially be a huge slowdown.