Search Unity

Enum becomes int in inspector

Discussion in 'Scripting' started by ElnuDev, Apr 21, 2018.

  1. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
    upload_2018-4-20_22-0-10.png
    In the top tier, State Of Node is "Start." However, later it becomes "0", why?
    My code:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [System.Serializable]
    4. public enum nodeState {
    5.     start, normal, link, end
    6. }
    7.  
    8. [System.Serializable]
    9. public class ConversationNode {
    10.  
    11.     public nodeState stateOfNode;
    12.     public string npcName;
    13.     public string text;
    14.     public Reply[] replies;
    15.  
    16. }
    17.  
    18. [System.Serializable]
    19. public class Reply {
    20.  
    21.     public string text;
    22.     public ConversationNode link;
    23.  
    24. }
     
  2. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
    tka4ykbogdan and ElnuDev like this.
  3. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
    SerializableEnum does not show in MonoDevelop, it is not a recognized function. :(
    This is the code given by Scott Webster Portfolio:

    Code (CSharp):
    1. public class NewBehaviourScript : MonoBehaviour {
    2.  
    3.     public enum ExampleEnum
    4.     {
    5.         EE_One,
    6.         EE_Two,
    7.         EE_Three,
    8.         EE_Four
    9.     }
    10.     [Serializable]
    11.     public class ExampleEnumClass : SerializableEnum<ExampleEnum> { }
    12.  
    13.     public ExampleEnumClass m_EnumVariable;
    14. }
     
  4. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
  5. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
    The code is included in a zip file attached to article.

    SerializableEnumEditor.cs


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEditor;
    4. using System;
    5.  
    6. [CustomPropertyDrawer(typeof(NewBehaviourScript.ExampleEnumClass))]
    7. public class SerializableEnumEditor : PropertyDrawer {
    8.  
    9.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    10.     {
    11.         EditorGUI.BeginProperty(position, label, property);
    12.  
    13.         position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
    14.  
    15.         int indent = EditorGUI.indentLevel;
    16.         EditorGUI.indentLevel = 0;
    17.  
    18.         SerializedProperty enumProperty = property.FindPropertyRelative("m_EnumValue");
    19.         SerializedProperty enumStringProperty = property.FindPropertyRelative("m_EnumValueAsString");
    20.  
    21.         for(int nameIndex = 0; nameIndex < enumProperty.enumNames.Length; nameIndex++)
    22.         {
    23.             if (enumProperty.enumNames[nameIndex] == enumStringProperty.stringValue)
    24.             {
    25.                 enumProperty.enumValueIndex = nameIndex;
    26.                 break;
    27.             }
    28.         }
    29.  
    30.         // Enum
    31.         enumProperty.enumValueIndex = EditorGUI.Popup(position, enumProperty.enumValueIndex, enumProperty.enumNames);
    32.         enumStringProperty.stringValue = enumProperty.enumNames[enumProperty.enumValueIndex];
    33.  
    34.         EditorGUI.EndProperty();
    35.     }
    36. }
    37.  
    SerializableEnumMaskEditor.cs

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEditor;
    4. using System;
    5.  
    6. [CustomPropertyDrawer(typeof(NewBehaviourScript.ExampleEnumAsMask))]
    7. public class SerializableEnumMaskEditor : PropertyDrawer
    8. {
    9.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    10.     {
    11.         EditorGUI.BeginProperty(position, label, property);
    12.  
    13.         position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
    14.  
    15.         int indent = EditorGUI.indentLevel;
    16.         EditorGUI.indentLevel = 0;
    17.  
    18.         SerializedProperty enumProperty = property.FindPropertyRelative("m_EnumValue");
    19.         SerializedProperty enumStringListProperty = property.FindPropertyRelative("m_EnumMaskValuesAsStrings");
    20.  
    21.         int maskValue = 0;
    22.         for (int arrayIndex = 0; arrayIndex < enumStringListProperty.arraySize; arrayIndex++)
    23.         {
    24.             for (int nameIndex = 0; nameIndex < enumProperty.enumNames.Length; nameIndex++)
    25.             {
    26.                 if(enumProperty.enumNames[nameIndex] == enumStringListProperty.GetArrayElementAtIndex(arrayIndex).stringValue)
    27.                 {
    28.                     maskValue |= 1 << (nameIndex);
    29.                 }
    30.             }
    31.         }
    32.         maskValue = EditorGUI.MaskField(position, maskValue, enumProperty.enumNames);
    33.  
    34.         enumStringListProperty.ClearArray();
    35.         // Enum
    36.         enumProperty.intValue = maskValue;
    37.         int currentIndex = 0;
    38.         for (int nameIndex = 0; nameIndex < enumProperty.enumNames.Length; nameIndex++)
    39.         {
    40.             if((maskValue & 1 << (nameIndex)) != 0)
    41.             {
    42.                 enumStringListProperty.InsertArrayElementAtIndex(currentIndex);
    43.                 enumStringListProperty.GetArrayElementAtIndex(currentIndex).stringValue = enumProperty.enumNames[nameIndex];
    44.                 currentIndex++;
    45.             }
    46.         }
    47.  
    48.         EditorGUI.EndProperty();
    49.     }
    50. }
    51.  
     
    ElnuDev likes this.
  6. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
    Geez, sorry my bad! :oops: 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:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [System.Serializable]
    4. public enum nodeState {
    5.     start, normal, link, end
    6. }
    7.  
    8. [System.Serializable]
    9. public class ConversationNode {
    10.  
    11.     public class stateOfNode : SerializableEnum<nodeState> { };
    12.     public string npcName;
    13.     public string text;
    14.     public Reply[] replies;
    15.  
    16. }
    17.  
    18. [System.Serializable]
    19. public class Reply {
    20.  
    21.     public string text;
    22.     public ConversationNode link;
    23.  
    24. }
     
  7. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
    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
    https://github.com/jacobdufault/ful...rializer/Source/Converters/fsEnumConverter.cs

    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
     
  8. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
    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??
     
  9. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
    Well, here we go. I manipulated the code a bit and now it is working BUT it is still become int instead of enum!!
    upload_2018-4-21_15-43-18.png
    My code:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [System.Serializable]
    4. public enum nodeState {
    5.     start, normal, link, end
    6. }
    7.  
    8. [System.Serializable]
    9. public class stateOfNode : SerializableEnum<nodeState> { }
    10.  
    11. [System.Serializable]
    12. public class ConversationNode {
    13.  
    14.     public stateOfNode currentStateOfNode;
    15.     public string npcName;
    16.     public string text;
    17.     public Reply[] replies;
    18.  
    19. }
    20.  
    21. [System.Serializable]
    22. public class Reply {
    23.  
    24.     public string text;
    25.     public ConversationNode link;
    26.  
    27. }
     
  10. ElnuDev

    ElnuDev

    Joined:
    Sep 24, 2017
    Posts:
    298
    Nevermind I found a workaround. :)
     
  11. chadfranklin47

    chadfranklin47

    Joined:
    Aug 11, 2015
    Posts:
    229
    Mind sharing? This is still an issue in 2023.
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    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. :)

    https://forum.unity.com/threads/bes...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!
     
  13. chadfranklin47

    chadfranklin47

    Joined:
    Aug 11, 2015
    Posts:
    229
    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.
     
    Last edited: Jul 3, 2023