What are enum flags and how to use them in Unity

Posted by : on

Category : C#   Unity

What are Enum Flags

When we define an enumeration we create a set that represents mutually exclusive values. For example we may need to create different behaviors for an enemy. To do that we define an enum like this:

public enum Behavior
{
    Idle,
    LookingForPlayer,
    Moving,
    Attacking
}

and then we define a Behavior type variable:

public Behavior EnemyBehavior;

This is serialized by Unity, so that we can use it and change its value in the Editor:

Unity Enum

The EnemyBehavior can have any of those values, but cannot contain two or more at the same time. In this example that is ok, because an enemy cannot have two different behaviors at the same time. But what if we need to represent values that are not mutually exclusive.

Let us suppose that we have a tile based game and the player can choose to go towards any of the four cardinal directions, but only if the tile allows it. For example a tile that is at the eastern edge of our map would not allow the player to move east, or a tile that North and South of it has tiles that represent impassable terrain, for example mountains, would only allow the player to move East and West. Representing the directions for each tile that a player is allowed to move with an enum, would be a problem, because a variable of our enum type can only hold one of those directions.

Representing those directions in our tiles with booleans is messy, there is nothing that ties those variables together and even if we create our own type that holds those booleans we increase the chance of bugs by forgetting to set each of those every time we need to describe new allowed directions. This solution also doesn’t scale very well, what if we want to have eight different directions in each of our tile, or we have a use case that a variable can have even more than eight different values and be allowed to have a combination of those values as well. Those are cases where Enum flags can be really useful.

Enum flags usage

By using the FlagsAttribute we indicate that our enum consists of bit fields. By doing that, we can use bitwise operations that can combine values or check for the existence of one of those values in a variable that holds a combination. To use the Flags attribute, we have to declare our enum, in a way that each of its values is represented by a bit set to 1 and all other bits set to 0. This can be done easily with two different ways:

[Flags] public enum Directions
{
    None = 0,
    North = 1,
    West = 2,
    South = 4,
    East = 8
}

or

[Flags] public enum Directions
{
    None = 0,
    North = 1 << 0,
    West = 1 << 1,
    South = 1 << 2,
    East = 1 << 3
}

Those two ways are equivalent and it is a matter of preference. The above code means that the North value will be a number that has all its bits set to zero, except the first, that will be one. West will be a number that has all its bits set to zero, except the second that will be one and so on. By using the Flags attribute we tell the compiler that he should treat the enumeration in a way that its values are not exclusive, so that the combination of those values gets displayed properly. For example the following code

AllowedDirections = Directions.East | Directions.West;
Debug.Log(AllowedDirections);

in Unity, will log West,East, but if we hadn’t used the flags attribute then it would log 10, which is the bitwise OR operation between 2 and 8.

A thing to notice here is the inclusion of the None value. Because C# always initializes our variables by setting all their bits to zero, the inclusion of the None value is a good idea, even if it doesn’t make sense in our code. Instead of None, it could indicate an invalid value, when we have forgotten to initialize one of our variables.

Operations between values in an Enum Flag

By doing bitwise operations in our enum flag values, we can add/remove a value in a variable, or check if a value is set.

We can add a value in an existing variable by using the bitwise OR operator (|) like this

AllowedDirections = Directions.East;
AllowedDirections = AllowedDirections | Directions.West;

or by using the compound assignment:

AllowedDirections = Directions.East;
AllowedDirections |= Directions.West;

with the above code we had created an AllowedDirections variable that contained the East direction and by using the bitwise OR operator our variable now holds both the the East and the West values.

To remove a value the code is equally simple

AllowedDirections = Directions.West | Directions.East;
AllowedDirections = AllowedDirections & ~Directions.West;

or in a shorter form

AllowedDirections = Directions.West | Directions.East;
AllowedDirections &= ~Directions.West;

the above code will remove the West value from our AllowedDirections variable that contained the West, East values, so that now will equal to East.

If this code seems confusing here is what happens:

At first our AllowedDirections variable has this representation (omitting the zeros at the beginning)

1010

and the Directions.West value has this representation:

0010

by using the bitwise NOT operator (~) we reverse the bits in the Directions.West value, the zeros become ones, and the ones become zeros. So the ~Directions.West is represented like this:

1101

Then by using the bitwise AND operator (&) we get :

1010 AND
1101 = 
---------
1000

that is, we set to 1 only the bits that are 1 in both values.

To check if a value exists in a variable

The bitwise operation is coded like this:

(AllowedDirections & Directions.East) == Directions.East

if the AllowedDirections variable contains the Directions.East value the above statement returns true.

C# also has the HasFlag method that executes the above logic, so the following code is equivalent:

AllowedDirections.HasFlag(Directions.East)

Something to have in mind here: If you want to check for the None Value, both of the above will return true, no matter the values that exist in the AllowedDirections variable. That happens because the bitwise AND operation with something that has all its bits set to zero (the None value), will always be equal to zero, no matter the value that we are checking. If we want to check if our variable has the None value, then we can use the Equals method to get the correct result:

AllowedDirections.Equals(Directions.None)

Bit representation of an Enum Flag variable

If you want to see the binary representation of an enum flag variable, C# has the Convert.ToString method that we can use to check our variables representation in binary. Its usage in our case would be like this:

var stringRepresentation = Convert.ToString((int)AllowedDirections, 2);

How to use Enum flags in Unity

In Unity the Flags attribute is also being used by the editor, so we can easily change values:

Unity Enum Flag

this allows us to select more than one value in the editor, but there is a potential problem here. Unity by default adds the Everything value as you can see in the image. If someone selects it in the Editor, Unity will automatically select the Everything value and all the values that we have defined, except the None value.

Someone would assume that this value is equal to a variable that has all our values, but this isn’t true. The Everything value doesn’t equal to AllowedDirections = Directions.North | Directions.West | Directions.South | Directions.East

The reason is this:

Our AllowedDirections variable has the following representation in binary:

0000 0000 0000 0000 0000 0000 0000 1111

but the Everything value is represented like this:

1111 1111 1111 1111 1111 1111 1111 1111

The Everything value sets all the bits to 1, so that it can contain future additions to our enum. That is an implementation decision by Unity that we should be aware of. If we want to check if a variable has all the values that we have defined in our enum, the right way to do it, would be:

  • To either create in our enum a value that is the bitwise OR of all our values and take care so that no one selects the Everything value in the editor, but uses our own. Or
  • sanitize the value every time that is being selected in the editor, like this:
private const Directions ALL_DIRECTIONS = Directions.North | Directions.West | Directions.South | Directions.East;

AllowedDirections &= ALL_DIRECTIONS;       

The first way has the risk of someone selecting the Everything value by mistake, the second way is safe from this mistake, but hurts our code’s extensibility, because we have to remember that every time we change the values our enum holds, to also change our const variable to represent the current all values.

This is it about enum flags and their usage in Unity. Thank you for reading and as always for questions and comments, use the comments section, or contact me directly via the contact form or email, also if you don’t want to miss any of the new articles, you can always subscribe to my newsletter or the RSS feed.


About Giannis Akritidis

Hi, I am Giannis Akritidis. Programmer and Unity developer.

Follow @meredoth
Follow me: