Enums in Unity

Enums in Unity (how they work and how to use them)

In Advanced Scripting by John FrenchUpdated 5 Comments

When you create a variable in Unity, the value it can be set to typically depends on what type of variable it is.

For example, a boolean can either true or false,

An integer is always going to be some kind of whole number,

While a reference variable points to an object or a script of that type elsewhere in your project.

Values and references like this can be checked, set, and compared with each other to create the logic in your game.

But what if you want to create your own kind of value?

Something that can’t be described using just true or false.

Or that would be difficult to manage with a number.

That’s where Enums come in handy.

Enums allow you to create a set of predefined values that are human-readable, and easy to understand.

They can be used to represent information that would be difficult to describe using other formats, such as seasons, difficulty or game states.

But how do they work? And how can you make your own?

Chances are, even if you’re just getting started with Unity, or with game development in general, you’ve probably already used an enum before.

But, even if you haven’t, once you get the hang of how they work, you’ll find that they can be surprisingly easy to use, and very useful.

In this article, you’ll learn what enums in Unity are, how they work, and when to use them so that you can make your project a little easier to work with.

Here’s what you’ll find on this page:

So what is an enum?

And what can you do with them?

What is an enum?

Generally speaking, an Enum is simply a set of named values.

They allow you to create variables that, although they’re technically just numbers, have human-readable labels.

As a result, enums can be used to create values for concepts that have a limited number of possible options, but that can’t be described in any other way.

Such as compass directions, seasons, states or a list of choices in a settings menu.

screenshot of a difficulty enum in Unity

Enums can be used to create sets of human-readable values, such as a difficulty setting.

You’ll also occasionally find enums used in Unity’s functions, where a method will take a particular type of enum as a paramter.

For example, Unity’s Raycast function accepts a parameter to include or exclude Trigger Colliders from its checks, the Query Trigger Interaction setting.

Query Trigger Interaction enum in Unity

The Query Trigger Interaction setting is simply an enum with three options.

Behind the scenes, this setting is an enum.

But why does it need to be?

You might expect that a setting like this would be a good candidate for a simple true or false parameter but, in practice, the function allows you to choose one of three settings, not two.

You can include triggers (Collide), exclude them (Ignore), or defer to the global setting (Use Global).

To do this without an enum, you’d need to use a different type of data to represent the settings instead.

A boolean wouldn’t provide enough options and, while you could use an integer, where 0, 1 and 2 set the value of the function, there are a couple of problems with doing it that way.

Mainly that it wouldn’t be clear which possible setting each number relates to and you wouldn’t know how many different options there were, meaning that it would be possible to choose an invalid option.

An enum, on the other hand, allows you to choose one of a known number of options, and provides the possible choices as written values, using labels that describe what they actually do.

An enum in Unity showing its possible options.

When typing an enum in code, auto-complete will typically show you which of the possible options you can choose from.

However, behind the scenes, they are just numbers.

Numbers that can be checked and compared efficiently and accurately, but that can be set using a value that actually makes some sense to the person that’s setting it.

This makes them ideal for any kind of dropdown selection that’s more complex than a true or false, but that is still represented by a limited number of known options.

So how do you make your own?

How to make an enum in Unity

Because an enum is just a data type that contains a predefined set of named values, they are actually very easy to create.

To make one, simply declare a public enum, using the enum keyword, give it a name, just like you would when creating a class type, and then, in the body of the enum, type out each of your enum’s options in a comma-separated list.

Like this:

public enum Direction
{
    North,
    East,
    South,
    West
}

You can create the enum in its own script file, in the body of another class or you might choose to type it out below the class that will typically use it.

Like this:

public class EnumExample : MonoBehaviour
{
    public Direction direction;
}

public enum Direction
{
    North,
    East, 
    South,
    West
}

And that’s it!

That’s all you need to do to create an enum.

You’ll then be able to use it in the same way as any other value.

By setting it in a script,

Like this:

public class EnumExample : MonoBehaviour
{
    public Direction direction;

    private void Start()
    {
        direction = direction.South;

        if (direction = Direction.South)
        {
            Debug.Log("South selected");
        }
    }
}

Or by setting it in the Inspector, where the enum will appear as a dropdown list.

Which looks like this:

Enum Dropdown List in Unity Inspector

A public or serialised enum will appear in the Inspector as a dropdown list.

How to make an enum visible in the Inspector

Enums are value types, meaning that an enum variable will be visible in the Inspector if it’s public, or if it’s serialized and private.

Unlike when writing a custom class or a struct, there’s no need to add the System Serializable attribute to the enum to make sure that it shows up in the Inspector.

However, in most cases, you will want to make your enum definition public, as the accessibility modifier you set when creating the enum will determine how accessible it can be when you come to use it in a script.

For example, public enums can be declared as public variables and can be used everywhere in your project.

While explicitly private enums must be declared inside of the body of the class that uses them, as writing them out beneath the class, or in a separate script file won’t work.

Enums that aren’t explicitly marked as private or public have kind of a hybrid accessibility. If they’re defined outside of the class, they can be used everywhere, but they can’t be made public. Although, they can be serialised using the Serialize Field attribute to show them in the Inspector.

But, if you define the enum inside of the body of another class, unless you explicitly mark it as public, it will be treated as private to that class only.

Enum examples

An enum can be extremely useful when you need to check a condition against one of a limited number of possible options.

For example, you could use an enum to check the game’s state, where different blocks of code are processed depending on which state the enum value is set to.

Like this:

public class StateMachineExample : MonoBehaviour
{
    public State currentState;

    void Update()
    {
        switch (currentState)
        {
            case State.Idle:
                Debug.Log("Do nothing");
                break;

            case State.Search:
                Debug.Log("Search for the player");
                break;

            case State.Attack:
                Debug.Log("Attack the player");
                break;
        }
    }
}

public enum State
{
    Idle,
    Search,
    Attack
}

In this example, the switch statement checks which state the variable is in and runs a different section of code in response.

This is an extremely common use for an enum, as being able to identify each state by name makes it much easier to manage than if you were using an arbitrary value, such as a number alone.

However, behind the scenes, that’s all an enum is.

The enum’s values are simply a set of integers, just like the index elements of an array.

It’s even possible to set an enum’s value using the numerical index of the element it relates to, by casting an integer to an enum of that type.

Like this:

direction = (Direction)2; // Sets the enum to South

However, because the values behind the user-readable labels are numbers, changing the order of an enum’s elements, such as adding a new one to the list, can cause the assigned values of each entry to change.

This means that the value of an enum on a script may also change if you reorder the elements.

As a result, it’s always best to avoid adding new options to an enum that’s already in use and, if you need to, to only add them to the bottom of the list.

However, this usually only happens when an enum is using implicit values, meaning that it’s using the default values that are assigned to each element automatically.

This is because, even though the order of the labels may have changed, the integers that are used to represent them will still be in their original sequence.

Changing the order of the labels, or adding a new one in between two existing options, will cause the numbers to correspond with different choices, which is why settings on scripts can silently change in response.

However, it is possible to manually choose the number that each enum element is assigned.

So how do an enum’s values work, and how can you set them yourself?

Enum values and how they work

An enum is basically just a number, typically an integer, just with a human-readable label attached to it and a limited number of options to choose from.

By default, the value of each option will be incremented by one, starting from zero, just like the elements of an array.

It’s possible to get the number behind an enum value by casting it to an Integer.

Like this

int i = (int)Direction.North;

However, it’s also possible to set the numerical value that relates to each option, manually, by initialising it to a specific number when creating the enum.

For example, you could give each direction, North, East, South, and West, an integer value that corresponds to the number of degrees around the compass.

Like this:

public enum Direction
{
    North = 0,
    East = 90, 
    South = 180,
    West = 270
}

While this can be useful for storing basic data together with a label, that’s not really what enums are for.

Enum values are generally used to identify their labels, not the other way around.

So why set an enum’s values at all?

As it turns out, there’s another reason why you might want to set the value of each option manually.

When you change the order of an enum’s elements, the default numbers that are used to identify them will not be reordered, but the labels will.

Each label gets a new number, and selections that have already been made in the Inspector can silently change to a different option.

While this can be frustrating and difficult to detect it is, technically, the correct behaviour, as the number of the selected option won’t actually have changed, it just relates to a different label now.

Giving each element its own value prevents this from happening, even if it’s just the number that it would have been assigned by default.

Like this:

public enum Direction
{
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

This allows you to change the order of the enum’s elements, or add new ones, without affecting values that have already been set.

Like this:

public enum Direction
{
    North = 0,
    NorthEast = 4,
    East = 1,
    SouthEast = 5,
    South = 2,
    SouthWest = 6,
    West = 3,
    NorthWest = 7,
}

This works because the order of elements in the Inspector’s dropdown list is determined by the written order in the enum, not its value.

But, because each value has already been paired with a specific number manually, changing the order doesn’t overwrite existing selections, because their number hasn’t changed.

How to count and use all of an enum’s elements

One of the main benefits of an enum is that it represents a limited number of known options.

Which can be useful, especially when working in a script, where the editor you’re using will typically show you which options you can choose from as you type it.

However, it’s also possible to get all of the elements in an enum using the Enum Class.

Like this:

string[] names = System.Enum.GetNames(typeof(DifficultySetting));

It works by getting all of the possible options from an enum and placing them in an Array.

This can be useful for counting and reading all of the possible choices an enum supports, such as to populate a list of options in a settings menu, for example.

Like this:

using TMPro;

public class EnumTests : MonoBehaviour
{
    public DifficultySetting difficultySetting;
    public TMP_Dropdown difficultySelection;

    private void Start()
    {
        List<TMP_Dropdown.OptionData> options = new();
        string[] names = System.Enum.GetNames(typeof(DifficultySetting));
        foreach (string name in names)
        {
            options.Add(new TMP_Dropdown.OptionData(name));
        }

        difficultySelection.AddOptions(options);
        difficultySelection.onValueChanged.AddListener(SetDifficulty);
    }

    public void SetDifficulty(System.Int32 index)
    {
        difficultySetting = (DifficultySetting)index;
    }
}

public enum DifficultySetting
{
    Easy,
    Normal,
    Hard
}

Enum default selection

When choosing values for your enum options, it’s important to remember that the default value of an enum will be whatever result is returned by Zero

What this means is, that, if you don’t have an option that’s associated with zero, then nothing will appear to be selected.

And if you try to read the value of the enum variable, you’ll get 0 back, even if you try to convert the enum to a string.

Like this:

public MyEnum myEnum;

private void Start()
{
    Debug.Log(myEnum.ToString());
}

This happens because invalid selections, such as choosing an enum by number when that number hasn’t been assigned a label, will simply return the number back as a result.

If you want to leave a setting blank until you choose what it should be then this might be exactly the behaviour you want.

Screenshot of a blank enum selection in the Unity Inspector

Enums are set to 0 by default but, if there isn’t a label associated with 0, the field will appear to be blank, and will return the number zero if queried.

Alternatively, you could simply always use the first element in the enum as a generic default option.

Like this:

public enum EnemyBehaviour
{
    PleaseSelect,
    Idle,
    Patrol,
    Attack
}

What happens if two enum elements have the same value?

While the numbers of your enum’s elements do not have to be sequential, or even anywhere near each other, they do have to be different.

This is because the number is the value’s unique identifier meaning that, if two elements have the same numerical value, they could be considered to be the same as each other.

Even if they’re not.

For example, two different directions that both use the same underlying value will return true when compared.

Like this: 

public class ComparingEnums : MonoBehaviour
{
    Direction direction1 = Direction.West;
    Direction direction2 = Direction.East;

    void CompareDirections()
    {
        if (direction1 == direction2)
        {
            Debug.Log("The directions are the same");
        }
    }
}

public enum Direction
{
    North = 0,
    East = 1,
    South = 2,
    West = 1,
}

This can be a problem if you try to use enums as a numerical data structure.

For example, if you simply want to pair a number with a name, but where any two of the numbers could be the same, enums aren’t really a good fit for that.

Instead, you’d be better off using your own data structure, such as a struct, or a plain class, that allows you to create grouped sets of fields that contain their own unique values.

Enums can be extremely useful for picking one option out of many.

But, what if you don’t want to pick just one option?

What if you want to create an enum that allows you to select multiple options?

How to create a multiple choice enum (using enum flags)

It’s possible to create a multiple choice enum in Unity that allow you select more than one option from a dropdown menu using Enum Flags.

This creates the same type of selection field as a Layer Mask, which allows you to choose any number of different layers from a single field.

Screenshot of a multiple-choice enum in Unity

It’s possible to create a multiple choice enum in Unity, allowing you to select more than one option.

Multiple choice enums work in a similar way, by using a Bit Mask to flag multiple options, using a single value, using ones and zeros.

So how can you make one?

To make a multiple choice enum, add the System Flags attribute to the enum’s definition.

Like this:

[System.Flags]
public enum Choice
{
    Nothing,
    OptionOne,
    OptionTwo,
    OptionThree,
    OptionFour
}

Next, in order for the multiple choice enum to work properly, you’ll need to manually set the value of each element to an incrementing number.

But, for this to work in the way you expect, each number must be a power of two.

So, for example, 1, 2, 4, 8, 16, 32, and so on.

Like this:

[System.Flags]
public enum Choice
{
    Nothing=0,
    OptionOne=1,
    OptionTwo=2,
    OptionThree=4,
    OptionFour=8
}

This is because the binary representation of each value will be used to decide which elements have been selected and which ones haven’t.

It works by reading the ones and zeros from right to left, where each one represents a selection.

So, for example, Option Three is represented by the decimal value 4.

But, when 4 is converted to binary, it reads as 100.

Reading the number from right to left marks the first and second values as zero, meaning that they’re not selected, while the third value is a one, meaning that it is, and that Option Three is selected.

Zero is used to select Nothing, while an Everything option, represented by Minus One is added and displayed after the first element automatically.

But why use these values specifically?

Using this method means that each element’s value doesn’t interfere with other settings.

Otherwise, if you were to leave the enum’s values to their default assignments, 1,2,3 and so on, then Option 3, which would be represented by 3 in decimal by default, would be 11 in binary, meaning that it would select options one and two, but leave three unchecked.

Which could be a little confusing and isn’t typically how you’d expect a multiple choice selection to work.

Once you’ve created your multiple choice enum, you’re going to need a way to read the values that have been set.

Generally, there are two ways to do this.

You can check to see if a particular value has been chosen with the Has Flag function, by passing in the element that you want to check for.

Like this:

if (choice.HasFlag(Choice.OptionOne))
{
    Debug.Log("Option One has been selected.");
}

This will return true if the specified flag is selected, in any combination with other choices.

But, what if you to check for a very specific combination only?

It’s possible to test the numerical value of the enum to see which flags have been chosen by casting it to an integer.

For example, the default value of Zero represents Nothing:

if ((int)choice == 0)
{
    Debug.Log("Nothing is selected");
}

While checking for Minus One tests for the Everything selection.

if ((int)choice == -1)
{
    Debug.Log("Everything is selected");
}

However, it’s also possible to test a very specific combination, such as options One and Four, for example, by adding the numerical values of those selections together and then testing for that.

Like this:

int requiredValue = (int)Choice.OptionOne + (int)Choice.OptionFour;
if ((int)choice == requiredValue)
{
    Debug.Log("One and Four selected only");
}

However, keep in mind that this will only check for the value that’s represented by the unique combination of those specific options.

Meaning that, if you select another value, even if the two you want are also selected, the numerical total of the enum will be different and the if condition will return false.

As a result, if you simply want to check that one or more options have been selected, regardless of what any other choices might be, then the Has Flag function is usually going to be the best way to do that.

Now it’s your turn

Now I want to hear from you.

How are you using enums in your project?

Are you using them to manage states, settings, or something else?

And what have you learned about using enums in Unity that you know someone else would find helpful?

Whatever it is, let me know by leaving a comment.

John French profile picture

by John French

Game audio professional and a keen amateur developer.

Get Game Development Tips, Straight to Your inbox

Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

How this content was created

This article was written using first-hand research and experience, without the use of AI. For more information on how Game Dev Beginner articles are written, see my writing policy.

Comments

  1. Thank you for the article. A very good read, as always.

    I’m using enums in a UAV simulator I’m working on, and they’re great both for state management (which flight mode the UAV currently has) and settings, e.g. to manage what UAV controls are available, as those change depending on flight modes and other things.

    One tip is that you can make options that are a combination of other options, like this:

    [Flags]
    public enum Controls
    {
    None = 0,
    Throttle = 1 << 0,
    Yaw = 1 << 1,
    Strafe = 1 << 2,
    Vertical = 1 << 3,
    Tilt = 1 << 4,
    ThrottleButton = 1 << 5,
    JoystickButton = 1 << 6,
    Zipline = 1 << 7,
    Cruise = 1 << 8,
    ZoomIn = 1 << 9,
    ZoomOut = 1 << 10,
    Snapshot = 1 << 11,
    CameraToggle = 1 << 12,
    FlightControls = Throttle | Yaw | Strafe | Vertical,
    Camera = ZoomIn | ZoomOut | Snapshot | CameraToggle
    }

    This way you can use controls.HasFlag(Controls.FlightControls) or controls.HasFlag(Controls.Camera) to easily work with multiple options.

    Also notice I'm using bitwise shift (1 << 0, 1 << 1, etc.) instead of 1, 2, 4, 8, etc. This does exactly the same, just another way of writing it that I find easier to read.

  2. In the code:

    if (choice.HasFlag(Choice.OptionOne))
    {
    Debug.Log(“Option One has been selected.”);
    }

    if “Choice” is an enum, what type of thing is “choice”?

Leave a Comment