I had discovered through experimentation that instead of doing the “1 << layer” in the Raycast function, you could store them all in a LayerMask like so:
Then just feed the raycast “groundLayers” as it’s LayerMask input.
It sort of confused me though, because how is it allowing multiple conditionals to be fed through a LayerMask?
And how exactly does << work here, I don’t understand how a bitwise operation is working in this context.
Lastly, involving those two questions, how does this little conditional I managed to get working, work?
I thought I knew a fair bit about C# and Unity now, but this bit of code still has me wondering how exactly it works. I would greatly appreciate it if someone more knowledgeable could explain this to me! I hate not knowing how exactly some of my code is working! Thanks.
00001000 //the 3rd bit is a 1, this mask is for layer 3 [0-based counting]
1 << X: shift left by X amount
1 = 00000001
1<<4 = 00010000 //a mask for layer 4
a|b: bitwise OR (result has 1s if either a or b have 1s)
(1<<2) = 00000100 //mask for layer 2
(1<<4) = 00010000 //mask for layer 4
(1<<2) | (1<<4) = 00010100 //mask for both layers 2 and 4 ("on layer 2 or on layer 4")
a&b: bitwise AND (result will only have 1s where both have 1s)
a = 00011100
b = 00010111
a&b = 00010100
a^b: bitwise XOR (result will only have 1s if ONLY one of a or b have 1s)
a = 00001010
b = 00001100
a&b = 00000110
Note: You can print the bitwise values of a number with:
value = (1<<2) | (1<<4); //for example
Debug.Log( System.Convert.ToString( value, 2 ) ); //should print 10100 [it trims leading zeros]
Thanks for taking the time, but the basics of bitwise functions wasn’t what I didn’t understand, I don’t understand how it’s actually managing to be useful for conditions here. How is my OR condition resulting in “0” when the first layer is one of the layer’s in my LayerMask? Wouldn’t a bitshift of some other layer number still result in a value with 1s? I can’t grasp how it’s actually managing to do anything meaningful in this situation.
Ahha, (i didnt spot this earlier) gameobject.layer returns an int from 0 to 31, not a layermask, so you need to
1 << colObj.gameObject.layer
From groundlayers = 1<< LayerMask.NameToLayer("Ground")) | 1<< xxxx....
groundlayers will have some bits set eg. 01001111
and 1 << colObj.gameObject.layer will be 00001000 (on layer 3)
a&b will be 00001000 = 8, which != 0 (and IF test fails)
but when colObj.gameObject.layer is NOT on a layer included in the groundlayers mask
eg 00100000
mask 01001111
= 00000000 = 0, and the test evaluates true
Bitwise “or” and “and” are different than regular logical “or” and “and”. I’d suggest that wikipedia bitwise article if you really want to understand it, but basically when you’re dealing with a bitmask (like the LayerMask), the “or” means “Add the two masks together”, while the “and” means “check if this mask is contained in the other mask”.
x = Dogs | Cats | Fish (a mask that contains dogs, cats, and fish.)
y = x Birds (check if x contains birds. It doesn’t, so y will be zero)
z = x Dogs (check if x contains dogs. It does, so z will be non-zero… specificlaly z will be “Dogs” but usually you don’t care what the actual value is)
Huh, I didn’t say it wasn’t working! haha, that’s what I’m confused about is that my code actually somehow works, and I don’t understand how. It’s weird because it triggers when I actually am touching those layers, so it’s working as I want it (even though it’s == 0), just structured really weird, operating in a way I don’t quite understand.
Though how you explain it with your method, I’m still having a hard time understanding from a math perspective how this can work consistently with any layer combination. My “groundlayers” LayerMask returns a single byte that is equal to a bit shifted combination of all the layers I put into it, correct? So how can it tell that the byte is made up of those different bytes? For example, if you had a bitmask that was made up of a Layer 5 and a Layer 6, well, how would it know when I did the comparison, that there isn’t a Layer 3 and a Layer 8 in that bitmask?
Because you’re comparing groundLayers, which is a proper bitmask, to gameObject.layer, which is not in bitmask form. To put it in bitmask form you’d use 1 << colObj.gameObject.layer
But we can have 31 different layers, how could it work that way, with each bit representing a number, when there’s only 8 bits? What happens when the layer numbers go past 8? I understand that you can have a mix of 0/1s to achieve different integer value, but I’m not seeing how once you go past 8, you’d be able to identify what values were used to make up that full 8 bit combination.
And yeah, it’s working, with all/only the layers in groundLayers.
I was only typing to 8 bits for simpler visualization
you shift bits so that you get a bitmask, otherwise you are trying to compare a bitmask with an integer
00000000000000000000000000000001 //(1<<0) mask from (1 << LayerMask.NameToLayer("zero"))
00000000000000000000000000000010 //(1<<1) mask from (1 << LayerMask.NameToLayer("one"))
00000000000000000000000000000100 //(1<<2) mask from (1 << LayerMask.NameToLayer("two"))
00000000000000000000000000001000 //(1<<3) mask from (1 << LayerMask.NameToLayer("three"))
00000000000000000000000000010000 //(1<<4) mask from (1 << LayerMask.NameToLayer("four"))
etc...
00000000000000000000000000001010 //(1 << LayerMask.NameToLayer("one")) | (1 << LayerMask.NameToLayer("three")) layers 1 OR 3
//lets say that colObj.gameObject is on layer 22, in binary this is
00000000000000000000000000010110 //To the program, this looks like a mask comprising 3 layers
//perform comparison between this and our actual mask
00000000000000000000000000001010
00000000000000000000000000010110 =
00000000000000000000000000000010 != 0
//according to this (incorrect) test, the object is on (layer 1 OR 3)
//you MUST bitshift the objects layer (1<<22) so that it is
00000000010000000000000000000000
00000000000000000000000000010110 =
00000000000000000000000000000000
Alright, I’m finally understanding this haha, the 8 bits was the biggest thing confusing me, it made me think all sorts of complex math was going on here to create 8 bit variations.
So << is basically just saying “set the bit in our LayerMask, at the position equal to this LayerNumber, to 1”, And the | is basically just adding each one to the LayerMask, since the LayerMask has a 1 bit set on it.
Not as complex as I was making it up to be in my head haha, thanks again everyone! No more mystery code!