Search Unity

Custom Editor Issue with List of List (of List) SerializedProperty

Discussion in 'Editor & General Support' started by ArtyBoomshaka, Feb 12, 2020.

  1. ArtyBoomshaka

    ArtyBoomshaka

    Joined:
    Mar 5, 2013
    Posts:
    226
    Hi there,

    I'm making a custom editor to import custom text data to store in a ScriptableObject to serve as a text database.

    Edit : Unity version is 2019.1.14f1

    The import seems to work as expected (checked via debugger) but the resulting stored data is wrong.
    Unless I'm doing something wrong I think I might have stumbled in a bug with the serialized properties API, specifically with the array methods.

    My data layout is as such :
    Code (CSharp):
    1. public class CharacterLinesBank
    2. {
    3.     [System.Serializable]
    4.     public class t_Character
    5.     {
    6.         public string        m_Name;
    7.         public List<string> m_Lines;
    8.     }
    9.  
    10.     [System.Serializable]
    11.     public class t_CharactersCollection
    12.     {
    13.         public List<t_Character> m_Characters;
    14.     }
    15.  
    16.     //-------------------------------------------------------------------------
    17.  
    18.     public List<t_CharactersCollection> m_LanguagesBanks;
    19. }
    20.  
    So I have a list of t_CharactersCollection, each element containing the same list of t_Character but in a different language.

    The editor code to import the data goes like this :
    Code (CSharp):
    1. m_LanguagesBanks.ClearArray();
    2. //for each language blob
    3. {
    4.     m_LanguagesBanks.InsertArrayElementAtIndex(m_LanguagesBanks.arraySize);
    5.     // get the current element
    6.     var characters = m_LanguagesBanks.GetArrayElementAtIndex(m_LanguagesBanks.arraySize - 1).FindPropertyRelative("m_Characters");
    7.  
    8.     //for each line in the language blob (a line contains data for a character)
    9.     {
    10.         characters.InsertArrayElementAtIndex(characters.arraySize);
    11.         var lines = characters.GetArrayElementAtIndex(characters.arraySize - 1).FindPropertyRelative("m_Lines");
    12.  
    13.         //for each ";"-separated string in the line
    14.         {
    15.             if (characterLine.StartsWith("#"))
    16.                 characters.GetArrayElementAtIndex(characters.arraySize - 1).FindPropertyRelative("m_Name").stringValue = characterLine;
    17.             else
    18.             {
    19.                 lines.InsertArrayElementAtIndex(lines.arraySize);
    20.                 lines.GetArrayElementAtIndex(lines.arraySize - 1).stringValue = characterLine;
    21.             }
    22.         }
    23.     }
    24. }
    When stepping into the importing algorithm everything works as expected but when inspecting the resulting serialized data, instead of having
    Code (CSharp):
    1. + Lang1
    2. |    + Character1InLang1
    3. |    |    + Line1InLang1
    4. |    |    + Line2InLang1
    5. + Lang2
    6. |    + Character1InLang2
    7. |    |    + Line1InLang2
    8. |    |    + Line2InLang2
    I get :
    Code (CSharp):
    1. + Lang1
    2. |    + Character1InLang1
    3. |    |    + Line1InLang1
    4. |    |    + Line2InLang1
    5. + Lang2
    6. |    + Character1InLang1
    7. |    |    + Line1InLang1
    8. |    |    + Line2InLang1
    9. |    + Character1InLang2
    10. |    |    + Line1InLang1
    11. |    |    + Line2InLang1
    12. |    |    + Line1InLang1
    13. |    |    + Line2InLang1
    14. |    |    + Line1InLang2
    15. |    |    + Line2InLang2
    Basically, when iterating through the resulting data in 3 nested loops I need to not reset the indices of the nested loops to access the right data like so :

    Code (CSharp):
    1.         int j = 0;
    2.         int k = 0;
    3.         for (int i = 0; i < m_LanguagesProperty.arraySize; i++)
    4.         {
    5.             // EN/FR/...
    6.             var characters = m_LanguagesBanks.GetArrayElementAtIndex(i).FindPropertyRelative("m_Characters");
    7.             for (; j < characters.arraySize; j++)
    8.             {
    9.                 var lines = characters.GetArrayElementAtIndex(j).FindPropertyRelative("m_Lines");
    10.                 for (; k < lines.arraySize; k++)
    11.                 {
    12.                     lines.GetArrayElementAtIndex(k).stringValue = EditorGUILayout.TextField(lines.GetArrayElementAtIndex(k).stringValue);
    13.                 }
    14.             }
    15.         }
    Which leads me to think there might be a bug either with the actual serialization of the nested lists, or with the implementation of FindPropertyRelative() when it comes to nested lists. Unless I've done something dumb without realizing, of course.

    Edit2 : after checking the actual asset it seems the issue is with the import or serialization.

    Any insight very much appreciated. :)
     
    Last edited: Feb 12, 2020
  2. ArtyBoomshaka

    ArtyBoomshaka

    Joined:
    Mar 5, 2013
    Posts:
    226
    Bump? Seems the issue is with the serialization through FindPropertyRelative() and InsertArrayElementAtIndex() calls.