Enums and Bitwise operators

Enums and Unity Editor

How to make life easier by making enum flags into mask fields in the Unity inspector.

EnumFlagAttribute.cs [Must be placed in a folder that is not Editor]

using UnityEngine;

public class EnumFlagAttribute : PropertyAttribute
{
 public string enumName;

 public EnumFlagAttribute() {}

 public EnumFlagAttribute(string name)
 {
    enumName = name;
 }
}

EnumFlagsAttributeDrawer.cs [Must be placed in the Editor folder]

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagDrawer : PropertyDrawer {
 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
 {
    EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute;
    Enum targetEnum = GetBaseProperty<Enum>(property);

    string propName = flagSettings.enumName;
    if (string.IsNullOrEmpty(propName))
    propName = property.name;

    EditorGUI.BeginProperty(position, label, property);
    Enum enumNew = EditorGUI.EnumMaskField(position, propName,   
    targetEnum);
    property.intValue = (int) Convert.ChangeType(enumNew,  
    targetEnum.GetType());

    EditorGUI.EndProperty();
 }

 static T GetBaseProperty<T>(SerializedProperty prop)
 {
    // Separate the steps it takes to get to this property
    string[] separatedPaths = prop.propertyPath.Split('.');

    // Go down to the root of this serialized property
    System.Object reflectionTarget =   
    prop.serializedObject.targetObject as object;
    // Walk down the path to get the target object
    foreach (var path in separatedPaths)
    {
       FieldInfo fieldInfo =  
       reflectionTarget.GetType().GetField(path);
       reflectionTarget = fieldInfo.GetValue(reflectionTarget);
    }
    return (T) reflectionTarget;
 }
}

It is important to note that Enum definition should also use power-of-two values. Bitwise shifts achieve this, they basically shift the bits of a number right (>>) or left (<<). If you have a decimal number, let’s say “1” and you shift it of one position to the left, you’ll have “10”. Another shift and you’ll get “100”. If shifting one position in base ten is equivalent to multiply (or divide) by ten, shifting one position in base two is equivalent to multiply (or divide) by two. This is why bitwise shifts can be used to easily create powers of two.

Test.cs [Attach this to a gameObject to see the property drawer in action]

using UnityEngine;
using System.Collections;
using System;

public enum MyEnum
{                      //BINARY DEC
  None = 0 &lt;&lt; 0,     //000000 0
  First = 1 &lt;&lt; 1,    //000001 1
  Second = 1 &lt;&lt; 2,   //000010 2
  Third = 1 &lt;&lt; 3,    //000100 4
  Fourth = 1 &lt;&lt; 4,   //001000 8
  Fifth = 1 &lt;&lt; 5,
  Sixth = 1 &lt;&lt; 6,
  Seventh = 1 &lt;&lt; 7,
  Eighth = 1 &lt;&lt; 8,
}

public class Test : MonoBehaviour 
{
  [EnumFlagAttribute]
  public MyEnum m_enum;

  public MyEnum m_lastEnum;
  public void Update()
  {
    if (m_lastEnum != m_enum) 
    {
      Debug.Log (m_enum);
      m_lastEnum = m_enum;
      if ((m_enum &amp; MyEnum.Fourth) != 0) 
                        {
        Debug.Log ("HAS FOURTH");
      }

    }
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *