Hello, I needed a way to select and store multiple Enums. I found this on the forum.
Attribute
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
public class EnumFlagsAttribute : PropertyAttribute
{
public EnumFlagsAttribute() { }
public static List<int> GetSelectedIndexes<T>(T val) where T : IConvertible
{
List<int> selectedIndexes = new List<int>();
for (int i = 0; i < System.Enum.GetValues(typeof(T)).Length; i++)
{
int layer = 1 << i;
if ((Convert.ToInt32(val) & layer) != 0)
{
selectedIndexes.Add(i);
}
}
return selectedIndexes;
}
public static List<string> GetSelectedStrings<T>(T val) where T : IConvertible
{
List<string> selectedStrings = new List<string>();
for (int i = 0; i < Enum.GetValues(typeof(T)).Length; i++)
{
int layer = 1 << i;
if ((Convert.ToInt32(val) & layer) != 0)
{
selectedStrings.Add(Enum.GetValues(typeof(T)).GetValue(i).ToString());
}
}
return selectedStrings;
}
public static bool IsSelected<T>(T val, int index) where T : IConvertible
{
int layer = 1 << index;
return ((Convert.ToInt32(val) & layer) != 0);
}
public static bool IsSelected<T>(T val, string name) where T : IConvertible
{
int index = Enum.GetNames(typeof(T)).ToList().IndexOf(name);
int layer = 1 << index;
return ((Convert.ToInt32(val) & layer) != 0);
}
}
Drawer
#if UNITY_EDITOR
using UnityEngine;
using System.Collections;
using System;
using UnityEditor;
[CustomPropertyDrawer(typeof(EnumFlagsAttribute))]
public class EnumFlagsAttributeDrawer : PropertyDrawer
{
public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label)
{
_property.intValue = EditorGUI.MaskField(_position, _label, _property.intValue, _property.enumNames);
}
}
#endif
And it works like I wanted it to.
The problem is that when I select multiple Objects with a script that uses this, all of them are assigned the same value. So that all selected values get overwritten.
I tried to fix it, but I couldnât get it to work properly, maybe someone here knows a fix for it.
I donât want to change the values, If I want to move them to another place, all get set to the same value. I have to select them separately and move them.
Itâs because your drawer is just always assigning to the field. You need to grab the value from the field, and only assign it to the serialized property if it changes from what the current value is.
Mind you, you should be using more robust methods for this such as scriptable objects or SerializeReference fields. Enums are a trap.
Also doesnât Unity already support Enum Flags enums?
You can also check out that solution I shared with you above. Itâs an enum-like with some nice features: for example, it automatically serializes into strings, but you work with it like it was an enum in code. Pretty much the best of the two worlds if you need a simple flow. The thread is also a full tutorial on how it was built.
It doesnât work with the flags however! Itâs intended only as a replacement when you really want like some damage types or monster types or whatever, and you want something simple yet reliable.
The best way would be to provide a text field, and simply type in what youâd like, because well, then you donât have to worry if you add or remove a type, itâs always reliably saved as a string. Sadly, however, text fields leave a lot to be desired, like youâre free to make spelling errors, you waste time typing, and then you have to compare strings in your code, itâs soo bad on so many fronts.
Well, this was my motivation to make this, itâs basically a type that you can declare like you would declare an enum, then use it in the code exactly the same (including the values if you need them), but you also get the editor behavior for free: the string serialization, the drop down, even a special ânoneâ field if youâre making a selector.
And if you decide against it at some later stage, you can rip it out, but your YAML files still contain a serialized string, so you donât lose any information. Itâs also usable with ScriptableObjects. I honestly believe it offers a lot of value to any flow.