Simplify drawing Enum Flags in Unity



In this publication, I will try to briefly talk about the type of enumeration in C # , its use as flags, as well as how to simplify their drawing in the Unity inspector .

What is Enum?


Enumerations are a significant type in C # , consisting of a set of constants. The keyword enum is used to declare it . Each enumerator has an integer value. The first one defaults to 0 , and subsequent ones increase by 1 .

enum Color
{
    Red, // 0
    Green, // 1
    Blue // 2
}

You can use initializers to override values.

enum Color
{
    Red = 1,
    Green = 2,
    Blue = 3
}

Each type of enumeration has a base type, which can be any integer type except char (the default is int ). It can also be specified explicitly.

enum Color : byte
{
    Red = 1,
    Green = 2,
    Blue = 3
}

Flags


Sometimes it becomes necessary to endow an entity with a number of properties. You can declare multiple fields or create a list, but sometimes a single listing is enough. To use the enumeration as flags, add the special attribute System.FlagsAttribute . This requires explicit initialization of values, each of which is raised to a power.

[System.FlagsAttribute]
enum Color : byte
{
    None = 0,
    Red = 1, // 2 ^ 0
    Green = 2, // 2 ^ 1
    Blue = 4 // 2 ^ 2
}

Using the bitwise OR operation, you can combine enumeration elements, and using the HasFlag (Enum) method, check for the presence of bit fields in an instance.

var color = Color.Red | Color.Green | Color.Blue;
var hasFlag = color.HasFlag(Color.Red | Color.Green); // True

You can also perform checks using the AND bitwise operation .

var aColor = Color.Red | Color.Green;
var bColor = Color.Green | Color.Blue;
// Проверка наличия битовых полей
var contains = (aColor & bColor) == bColor; // False
// Проверка пересечения битовых полей
var overlaps = (aColor & bColor) != 0; // True

Transfers in Unity


For example, take the code below.

using UnityEngine;
public enum Color
{
    Red,
    Green,
    Blue
}
public class Example : MonoBehaviour
{
    public Color Color;
}

Unity's built-in tools allow you to display enumerations in a drop-down list.



Unfortunately, the editor cannot automatically draw enumerations in the form of flags. For these purposes, redefinition of the inspector is required, which is far from always convenient. But you can go for the trick and redefine drawing enumerations globally. First, modify the example.

using System;
using UnityEngine;
[Flags]
public enum Color
{
    Red = 1,
    Green = 2,
    Blue = 4
}
public class Example : MonoBehaviour
{
    public Color Color;
}

Next, you need to implement your PropertyDrawer . If the serializable property has the Flags attribute , then we will use the EditorGUI.MaskField method for drawing , and otherwise the standard EditorGUI.PropertyField method . Also note that a property can be an element of an array. The code below should be placed in a folder called Editor .

[CustomPropertyDrawer(typeof(Enum), true)]
public sealed class EnumPropertyDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        using (new EditorGUI.PropertyScope(position, label, property))
        {
            if (HasEnumFlagsAttribute())
            {
                var intValue = EditorGUI.MaskField(position, label, property.intValue, property.enumDisplayNames);
                if (property.intValue != intValue)
                {
                    property.intValue = intValue;
                }
            }
            else
            {
                EditorGUI.PropertyField(position, property, label);
            }
        }
        bool HasEnumFlagsAttribute()
        {
            var fieldType = fieldInfo.FieldType;
            if (fieldType.IsArray)
            {
                var elementType = fieldType.GetElementType();
                return elementType.IsDefined(typeof(FlagsAttribute), false);
            }
            return fieldType.IsDefined(typeof(FlagsAttribute), false);
        }
    }
}

Now the field is correctly displayed in the inspector for any Enum type.



In addition to certain enumeration values, the editor adds two more:

  • Nothing - has an integer value of 0 ;
  • Everything - has an integer value of -1 .

Related Links



Also popular now: