What's the difference between single ampersnad and double ampersands script operator?

In this example, why use single ampersand instead of double ampersand?
Please explain…

grounded = ((controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0);

(note grounded is a boolean variable)

2 Answers

2

The point is both “and” operators are operators that requires two values of the same type. The logical-and (&&) only operates on boolean values. The bitwise-and (&) operates on integer values and boolean values. The operator doesn’t compare the values, it performs a boolean-operation on the operants and returns a result. In case of the logical and the result will be also a boolean. The bitwise operator return the type of the operants.

In your example:

grounded = ((controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0);

the Move() function of CharacterController returns a bit flag which is simply an integer (int) (see the note at the end).

The collision flags are defined as:

public enum CollisionFlags
{
    None = 0,
    Sides = 1,
    Above = 2,
    Below = 4,
}

Only the lowest 3 bits of the integer are used

// The lowest byte
0000 0000
      ||\___ Sides
      |\____ Above
      \_____ Below

A bit flag is almost like a set of boolean values. Each bit in the integer represents a seperate boolean value (a 32Bit integer can hold up to 32 boolean values in one variable)

The actual number of the integer is irrelevant. In the case above if you collide below and at the sides the value would be 5 (or binary 0000 0101).

A bitwise and operation will perform a logical and operation between the same bits of the two operants.

In the case above you want to test if it collides below, so you want to know if the below-bit is set.

This operation can only return either “0” or “4”

(controller.Move(...) & CollisionFlags.Below)

    // case one:
    0000 0000     // value returned by move, not collided
AND 0000 0100     // the CollisionFlags.Below value
=   0000 0000     // result is 0

    // case two:
    0000 0001     // value returned by move, we collided only with the sides
AND 0000 0100     // the CollisionFlags.Below value
=   0000 0000     // result is 0

    // case three:
    0000 0100     // value returned by move, collided only below
AND 0000 0100     // the CollisionFlags.Below value
=   0000 0100     // here we have the value 4

    // case four:
    0000 0101     // value returned by move, we collided with the sides and below
AND 0000 0100     // the CollisionFlags.Below value
=   0000 0100     // result is also 4

In addition to this bitwise filtering we just test the returned value if it’s not 0 (therefor must be 4 because that’s what we filtered). The result of the != comparison is a boolean value true or false. It’s true when the below bit is set and false if the bit is not set.

Note: An enum represents an own type but behind the scenes it’s always a nummerical value. Enums help you to understand what bit is used for what. Keep in mide that each bit can only be used once. The nummerical value of a specific bit can be calculated with the bit shift operator. The lowerst bit is the bit 0 the second bit is the bit1… and so on.

To get the value of the third bit (bit2) just do (1<<2) which is 4 (binary 0000 0100)

The value of bit5 is (1<<5) == 32 (binary 0010 0000)

Right, I know that, I was just stressing the difference when using them in if statements. And I also know the unary & is a different operator, but the question was "what's the difference between a single and a double ampersand" ;). By the way, in many programming languages -x simply doesn't exist and gets replaced by the compiler by 0-x. And I see your double - and raise it with the three meanings of () ^^

A double ampersand will do a logical comparison between your two values. A single ampersand will perform a bitwise comparison between the two values. See these links (1, 2) for more info (I believe it’s the same deal as in C#).