- Home /
Default Editor : Enum as flags ?
Hello there !
I juste have a little question regarding Unity default editor with enums. By default, when you declare an enum, it will create an editor when you can choose the enum value but you'll only be able to pick one of those.
Is there a way like an special attribute to tell Unity "this is a flag, enable me to pick as many values as I want" without writing a custom editor ?
Thanks in advance for your answers :)
Yes I guess I could do that, but I've always found bool inelegant for context like that. I'll wait to see if there's a better solution but I'll probably go for yours if there's nothing else to do. Thanks for your answer anyway :)
Well, I mean, by definition, each enum variable can hold only 1 value. You could technically make several enums of the same type, but that's WAYYY messier than just using bools for the flags :)
Well I never had any trouble using enum as flags with bitwise operator and I've always found that method more elegant. :) But it does not seem Unity provide a simple way to show it in editor unless you use $$anonymous$$askField (which requires a lot of things so there's no way Unity does that himself).
Answer by froodydude · Aug 13, 2013 at 11:59 AM
This bugs me too but after some quick experimentation I think you can do it pretty trivially using the property drawer stuff. The main thing I noticed is to be aware of how Unity treats "Everything" as this sets all bits. I suspect it will also run in to problems if you leave gaps in your flags. I couldn't find a way to get the actual System.Type from the SerializedProperty, if it were possible to get this then you could make it more robust and also decide whether you want everything to mean set all bits or not. Anyway the code:
public class EnumFlagsAttribute : PropertyAttribute
{
public EnumFlagsAttribute() { }
}
[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 );
}
}
To use this you do the following:
[System.Flags]
public enum MyMaskedEnum
{
Flag0 = (1 << 0),
Flag1 = (1 << 1),
Flag2 = (1 << 2),
Flag3 = (1 << 3),
}
class MyObject : MonoBehaviour
{
[SerializeField] [EnumFlagsAttribute] MyMaskedEnum m_flags;
}
I like this! Probably worth mentioning that the attribute class must exist in a non-editor script and folder, and the property drawer class must exist in an editor script and folder. I had them in the same file as seems to be implied above. That tripped me up and it took some staring at the PropertyDrawer docs to figure it out.
For some reason the built-in "Everything" option is uncheckable for me. I use a custom definition for "All" in the enum, which is nice to have control over. I also like to define "None" in my enum as well as some combos that I use for mask testing, but don't intend for the field to be set to. Guess I'll mess with the editor UI a bit to see if I can suppress certain options.
UPDATE: found an alternative complete solution
http://answers.unity3d.com/questions/393992/custom-inspector-multi-select-enum-dropdown.html
Note that this solution works if and only if your enum values are consecutive bits (1, 2, 4, 8, ...). If you have a 0 value ("None") or combined values, then EditorGUI.$$anonymous$$askField isn't sufficient.
For a complete solution, see the link mentioned in previous comment (http://answers.unity3d.com/questions/393992/custom-inspector-multi-select-enum-dropdown.html)
Warning: The code in this answer isn't friendly to multiple-selection. As soon as you select two objects, the enum flags get overwritten without warning and with no way to undo. Here's my version of OnGUI that checks for changes before assigning. This is way safer.
public override void OnGUI(Rect _position, UnityEditor.SerializedProperty _property, GUIContent _label)
{
// Change check is needed to prevent values being overwritten during multiple-selection
UnityEditor.EditorGUI.BeginChangeCheck ();
int newValue = UnityEditor.EditorGUI.$$anonymous$$askField( _position, _label, _property.intValue, _property.enumNames );
if (UnityEditor.EditorGUI.EndChangeCheck ()) {
_property.intValue = newValue;
}
}
Very elegant but doesn't handle multi selection. Add this right after OnGUI{
EditorGUI.show$$anonymous$$ixedValue = _property.has$$anonymous$$ultipleDifferentValues;
Thanks a ton, I used this in the past. Luckily since Unity some 2019 version, this is not needed any more, b/c Unity now does this by default!
Answer by Democide · Feb 17, 2015 at 04:44 PM
I've also had this issue, and decided to build a different solution: Toggle Buttons.
It provides a better overview over the flags set but takes up more space in the Editor. You can check it out here:
http://www.sharkbombs.com/2015/02/17/unity-editor-enum-flags-as-toggle-buttons/
I made a few modifications to $$anonymous$$artin's code (posted to comments of the link provided), which provide stacked buttons if you have a long list of flags in your enum.
![Stacked Toggle Buttons][1] [1]: /storage/temp/80586-screen-shot-2016-10-21-at-23229-pm.png
Answer by Cookie042 · Feb 16, 2020 at 09:14 PM
As of writing this, just tag the enum definition as [System.Serializable, System.Flags] and unity will make the inspector ui work like a LayerMask. Makes everything on this page irrelevant. (using 2019.3 but i'm sure it has been there for a while)
Only has been a recent (and very welcome) addition to Unity default functionality.
Answer by TonyLi · Jul 04, 2013 at 08:41 PM
(( Doh, sorry, I have to apologize. I thought it did what I described below, but I forgot that I had written a custom inspector just to handle this one case. Never mind! :-) ))
You just need to use [System.Flags]. Unity will pick this up and treat the enum drop-down as a mask.
For example, in one of my projects, I defined a bit flag enum like this:
[System.Flags]
public enum QuestStatus {
Unassigned = 0x1,
Active = 0x2,
Success = 0x4,
Failure = 0x8
}
Then I have a component similar to this:
public class Quest : MonoBehaviour {
QuestStatus questStatus;
}
And the default inspector looks like the attached screenshot:
Doh, sorry, I have to apologize. I thought it did, but I forgot that I had written a custom inspector just to handle this one case. Never $$anonymous$$d! :-)
Old thread but well, this does allow you to get several at once, then you need a quick bit manipulation to figure out what is on.
QuestStatus _status = QuestStatus.Active | QuestStatus.Success;
then you check what is on with:
if((_status & QuestStatus.Active)==QuestStatus.Active)
print("Active");
else
print("No active");
Please note that although this solution looks magical, it doesn't appear to be working in Unity 5.5+
bunny83's answer below is a good solution. I think at the time I posted my response Unity Answers there wasn't a good way to retract/delete posts. I had forgotten that I'd written a custom inspector similar to bunny83's answer.
Answer by s_guy · Oct 19, 2013 at 02:05 AM
The answer posted by bunny83 solves this fully.
http://answers.unity3d.com/questions/393992/custom-inspector-multi-select-enum-dropdown.html