- Home /
Is "enum x : UInt32" cast to "enum x : int" when serializing?
I have an enum defined like this:
public enum MessageId : UInt32
{
StartPingCheck = 0x00000001,
CompletePingCheck = 0x00000002,
AgentUpdate = 0x00000004,
CoarseLocationUpdate = 0x0000ff06,
AttachedSound = 0x0000ff0d,
Wrapper = 0xffff0001,
UseCircuitCode = 0xffff0003
}
When using a value of this type in the inspector, I see all the values in the popup, but I can't select any of the values with the top bit set, in this case "Wrapper" and "UseCircuitCode". When selecting any of these, the value in the editor becomes blank.
Is this a bug, by design or am I doing something wrong?
EDIT: The actual value becomes zero when selecting the large values.
Answer by Namey5 · May 14, 2021 at 12:55 PM
This would make sense as I would imagine Unity stores all enums as though they are flags, with the implicit 'Everything' field always set to -1. The SerializedProperty only has value properties for intValue and longValue as well - and according to the docs, uint values will be set via the intValue field (and therefore implicitly cast to int32 for some reason). To get around this, you can make a custom PropertyAttribute and PropertyDrawer that uses 'property.longValue' instead (as long as you don't need ulong);
using System;
using UnityEngine;
public class UIntEnumAttribute : PropertyAttribute
{
public Type type;
public bool flags;
public UIntEnumAttribute (Type a_Type, bool a_Flags = false)
{
type = a_Type;
flags = a_Flags;
}
}
PropertyDrawer (in an Editor folder):
using System;
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer (typeof (UIntEnumAttribute))]
public class UIntEnumDrawer : PropertyDrawer
{
public UIntEnumAttribute EnumAttribute => (UIntEnumAttribute)attribute;
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
Enum value = (Enum)Enum.ToObject (EnumAttribute.type, (uint)property.longValue);
if (EnumAttribute.flags)
{
value = EditorGUI.EnumFlagsField (position, label, value);
}
else
{
value = EditorGUI.EnumPopup (position, label, value);
}
property.longValue = (uint)Enum.ToObject (EnumAttribute.type, value);
}
}
Usage example:
public enum MessageId : uint
{
StartPingCheck = 0x00000001,
CompletePingCheck = 0x00000002,
AgentUpdate = 0x00000004,
CoarseLocationUpdate = 0x0000ff06,
AttachedSound = 0x0000ff0d,
Wrapper = 0xffff0001,
UseCircuitCode = 0xffff0003
}
[SerializeField, UIntEnum (typeof (MessageId))] private MessageId m_MessageID = MessageId.StartPingCheck;
You are a star! Not only did you answer the question, you also provided a working solution to the issue caused by it! Thank you very much!