Enum becomes int in inspector


In the top tier, State Of Node is “Start.” However, later it becomes “0”, why?
My code:

using UnityEngine;

[System.Serializable]
public enum nodeState {
    start, normal, link, end
}

[System.Serializable]
public class ConversationNode {

    public nodeState stateOfNode;
    public string npcName;
    public string text;
    public Reply[] replies;

}

[System.Serializable]
public class Reply {

    public string text;
    public ConversationNode link;

}

start is 0… but i guess u mean u want the string names

2 Likes

SerializableEnum does not show in MonoDevelop, it is not a recognized function. :frowning:
This is the code given by Scott Webster Portfolio:

public class NewBehaviourScript : MonoBehaviour {

    public enum ExampleEnum
    {
        EE_One,
        EE_Two,
        EE_Three,
        EE_Four
    }
    [Serializable]
    public class ExampleEnumClass : SerializableEnum<ExampleEnum> { }

    public ExampleEnumClass m_EnumVariable;
}

Yes that is what I want. :slight_smile:

The code is included in a zip file attached to article.

SerializableEnumEditor.cs

using UnityEngine;
using System.Collections;
using UnityEditor;
using System;

[CustomPropertyDrawer(typeof(NewBehaviourScript.ExampleEnumClass))]
public class SerializableEnumEditor : PropertyDrawer {

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        SerializedProperty enumProperty = property.FindPropertyRelative("m_EnumValue");
        SerializedProperty enumStringProperty = property.FindPropertyRelative("m_EnumValueAsString");

        for(int nameIndex = 0; nameIndex < enumProperty.enumNames.Length; nameIndex++)
        {
            if (enumProperty.enumNames[nameIndex] == enumStringProperty.stringValue)
            {
                enumProperty.enumValueIndex = nameIndex;
                break;
            }
        }

        // Enum
        enumProperty.enumValueIndex = EditorGUI.Popup(position, enumProperty.enumValueIndex, enumProperty.enumNames);
        enumStringProperty.stringValue = enumProperty.enumNames[enumProperty.enumValueIndex];

        EditorGUI.EndProperty();
    }
}

SerializableEnumMaskEditor.cs

using UnityEngine;
using System.Collections;
using UnityEditor;
using System;

[CustomPropertyDrawer(typeof(NewBehaviourScript.ExampleEnumAsMask))]
public class SerializableEnumMaskEditor : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        SerializedProperty enumProperty = property.FindPropertyRelative("m_EnumValue");
        SerializedProperty enumStringListProperty = property.FindPropertyRelative("m_EnumMaskValuesAsStrings");

        int maskValue = 0;
        for (int arrayIndex = 0; arrayIndex < enumStringListProperty.arraySize; arrayIndex++)
        {
            for (int nameIndex = 0; nameIndex < enumProperty.enumNames.Length; nameIndex++)
            {
                if(enumProperty.enumNames[nameIndex] == enumStringListProperty.GetArrayElementAtIndex(arrayIndex).stringValue)
                {
                    maskValue |= 1 << (nameIndex);
                }
            }
        }
        maskValue = EditorGUI.MaskField(position, maskValue, enumProperty.enumNames);

        enumStringListProperty.ClearArray();
        // Enum
        enumProperty.intValue = maskValue;
        int currentIndex = 0;
        for (int nameIndex = 0; nameIndex < enumProperty.enumNames.Length; nameIndex++)
        {
            if((maskValue & 1 << (nameIndex)) != 0)
            {
                enumStringListProperty.InsertArrayElementAtIndex(currentIndex);
                enumStringListProperty.GetArrayElementAtIndex(currentIndex).stringValue = enumProperty.enumNames[nameIndex];
                currentIndex++;
            }
        }

        EditorGUI.EndProperty();
    }
}
1 Like

Geez, sorry my bad! :sweat_smile: I tried to get it into my script but now ‘State of Node’ isn’t appearing at all in the inspector. Any idea why? Here is my code integrated with the stuff from the zip file:

using UnityEngine;

[System.Serializable]
public enum nodeState {
    start, normal, link, end
}

[System.Serializable]
public class ConversationNode {

    public class stateOfNode : SerializableEnum<nodeState> { };
    public string npcName;
    public string text;
    public Reply[] replies;

}

[System.Serializable]
public class Reply {

    public string text;
    public ConversationNode link;

}

i am sorry that code is a mess but it is something like that will try and get it working later
ya it normally just saves them as ints you need to do the conversion to string manually if that is what you want
the nameof operator was recently added might be usefull for getting names of enums

https://github.com/jacobdufault/fullserializer

this free unity3d serialization addon does do enum by name and option to use int and many other features for serialization

but why do you need them saved as strings? saved as int should be fine unless human read or edit saved file right? maybe i just misunderstood your bug

Well, I am making a conversation asset for my RPG, and I need to have these text values in the inspector. So yes having the strings is required. There must be some way of getting this working without 3rd party code??

Well, here we go. I manipulated the code a bit and now it is working BUT it is still become int instead of enum!!


My code:

using UnityEngine;

[System.Serializable]
public enum nodeState {
    start, normal, link, end
}

[System.Serializable]
public class stateOfNode : SerializableEnum<nodeState> { }

[System.Serializable]
public class ConversationNode {

    public stateOfNode currentStateOfNode;
    public string npcName;
    public string text;
    public Reply[] replies;

}

[System.Serializable]
public class Reply {

    public string text;
    public ConversationNode link;

}

Nevermind I found a workaround. :slight_smile:

Mind sharing? This is still an issue in 2023.

Enums enums are bad in Unity3D if you intend them to be serialized:

They were bad when this thread was started in 2018 and they’re still bad today. :slight_smile:

https://forum.unity.com/threads/best-practice-to-find-object-in-list-of-custom-classes-do-if-in-list-if-not-do-something-else.972093/#post-6323361

https://forum.unity.com/threads/unity-card-game-structure.1006826/#post-6529526

It is much better to use ScriptableObjects for many enumerative uses. You can even define additional associated data with each one of them, and drag them into other parts of your game (scenes, prefabs, other ScriptableObjects) however you like. References remain rock solid even if you rename them, reorder them, reorganize them, etc. They are always connected via the meta file GUID.

Collections / groups of ScriptableObjects can also be loaded en-masse with calls such as Resources.LoadAll<T>().

Best of all, Unity already gives you a built-in filterable picker when you click on the little target dot to the right side of a field of any given type… bonus!

3 Likes

I appreciate the advice, I may make use of it elsewhere. But here, for my simple need to serialize a UnityEngine.Rendering.CompareFunction enum, scriptable objects would be a bit overkill.

Just to clarify, my only issue is the Unity Inspector (seemingly infrequently) displaying the enum field as an integer rather than the string name.