Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Issues with arrays on my custom editor

Discussion in 'Scripting' started by PaperMouseGames, Aug 29, 2019.

  1. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Hi there, not sure if this is the right place to ask this, but I'm having issues with a custom editor I've been working on. This is my first real custom editor and I can't seem to get an array to change its members using
    EditorGUILayout.ObjectField
    . The values in the array keep resetting when I change them.

    Here's me editor code:

    Code (CSharp):
    1. [CustomEditor(typeof(LootTable))]
    2. public class LootTableEditor : Editor
    3. {
    4.     int labelSize = 40;
    5.     int lootSize = 250;
    6.     int oddsSize = 100;  
    7.     int tableSize = 1;
    8.     bool foldout = true;
    9.     LootTable lootTable;
    10.  
    11.     ItemData[] itemDatas;
    12.     float[] odds;
    13.  
    14.     private void OnEnable()
    15.     {
    16.         lootTable = (LootTable)target;
    17.     }
    18.  
    19.     public override void OnInspectorGUI()
    20.     {
    21.         labelSize = EditorGUILayout.IntField("Label Size:", labelSize);
    22.         lootSize = EditorGUILayout.IntField("Loot Field Size:", lootSize);
    23.         oddsSize = EditorGUILayout.IntField("Odds Field Size:", oddsSize);
    24.        
    25.  
    26.         tableSize = EditorGUILayout.IntField("Table Size:", tableSize);
    27.         itemDatas = new ItemData[tableSize];
    28.         odds = new float[tableSize];
    29.  
    30.         foldout = EditorGUILayout.Foldout(foldout, "Table");
    31.  
    32.         if (foldout)
    33.         {
    34.             for (int i = 0; i < tableSize; i++)
    35.             {
    36.                 GUILayout.BeginHorizontal();
    37.  
    38.                 EditorGUIUtility.labelWidth = labelSize;
    39.  
    40. // This is where the issue is
    41.  
    42.                 itemDatas[i] = (ItemData) EditorGUILayout.ObjectField("Loot: ", itemDatas[i], typeof(ItemData), false, GUILayout.Width(lootSize));
    43.                 odds[i] = EditorGUILayout.FloatField("Odds: ", odds[i], GUILayout.Width(oddsSize));
    44.  
    45.                 GUILayout.EndHorizontal();
    46.             }
    47.         }
    48.     }
    So I'm trying to add ItemData ScriptableObjects and floats to specify odds to this loot table but every time I change a value in the inspector it gets reset to null or 0 immediately.

    I'm not having this issue with the int values like labelSize, only with the 2 values that are in the arrays.

    My goal is to set these values in this inspector, then once they're set, pass them onto the LootTable ScriptableObject (which this is the editor off) to set up the table.

    Any help with this would be really appreciated!
     
  2. CurtisMcGill

    CurtisMcGill

    Joined:
    Aug 7, 2012
    Posts:
    67
    You are trying to convert an ItemData to object and that does not work. Have you tried changing ItemData to object?

    Just guessing since I have not seen the item data class.

    Code (CSharp):
    1. [CustomEditor(typeof(LootTable))]
    2. public class LootTableEditor : Editor
    3. {
    4.     private int labelSize = 40;
    5.     private int lootSize = 250;
    6.     private int oddsSize = 100;
    7.     private int tableSize = 1;
    8.     private bool foldout = true;
    9.     private LootTable lootTable;
    10.  
    11.     private UnityEngine.Object[] itemDatas;
    12.     private float[] odds;
    13.  
    14.     private void OnEnable()
    15.     {
    16.         lootTable = (LootTable) target;
    17.     }
    18.  
    19.     public override void OnInspectorGUI()
    20.     {
    21.         labelSize = EditorGUILayout.IntField("Label Size:", labelSize);
    22.         lootSize = EditorGUILayout.IntField("Loot Field Size:", lootSize);
    23.         oddsSize = EditorGUILayout.IntField("Odds Field Size:", oddsSize);
    24.         tableSize = EditorGUILayout.IntField("Table Size:", tableSize);
    25.  
    26.         itemDatas = new UnityEngine.Object[tableSize];
    27.         odds = new float[tableSize];
    28.  
    29.         foldout = EditorGUILayout.Foldout(foldout, "Table");
    30.  
    31.         if (foldout)
    32.         {
    33.             for (int i = 0; i < tableSize; i++)
    34.             {
    35.                 GUILayout.BeginHorizontal();
    36.  
    37.                 EditorGUIUtility.labelWidth = labelSize;
    38.  
    39. // This is where the issue is
    40.                 itemDatas[i] =
    41.                     EditorGUILayout.ObjectField(itemDatas[i], typeof(ItemData), false, GUILayout.Width(lootSize));
    42.                 odds[i] = EditorGUILayout.FloatField("Odds: ", odds[i], GUILayout.Width(oddsSize));
    43.  
    44.                 GUILayout.EndHorizontal();
    45.             }
    46.         }
    47.     }
    48. }
     
  3. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    @CurtisMcGill

    I'll give this a try as soon as I can, but that doesn't explain why I'm having the same issue with
    odds[i] = EditorGUILayout.FloatField("Odds: ", odds[i], GUILayout.Width(oddsSize));
    .

    That's just a float so I would think it should be working.
     
  4. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Sorry to be hard headed, but I'm a beginner. Do you mean no errors as in, it's compiling? Because my code is compiling, it's just that I can't actually change the values of odds and ItemData.

    But I can change the value of the other non-array elements. I'm using 2018.3.4f1 though, so I guess I could try to upgrade? I was scarred to do it mid-project haha
     
  5. CurtisMcGill

    CurtisMcGill

    Joined:
    Aug 7, 2012
    Posts:
    67
    What version of Unity are you using?

    In the script, I posted there are no errors in 2019. The odds are working because you are adding float array to float GUI layout.

    The error is converting the ItemData to UnityEngine.Object. When you should be converting UnityEngine.Object to ItemData.

    The UnityEngine.Object is a generic object and any item can be saved as Object. You tell the GUI what kind of Object you are passing with Type of.

    I had to remove the "Loot" string as 2019 had no EditorGUILayout.ObjectField with string.
     
  6. CurtisMcGill

    CurtisMcGill

    Joined:
    Aug 7, 2012
    Posts:
    67
    Do not upgrade the project, I will test in 2018.
     
  7. CurtisMcGill

    CurtisMcGill

    Joined:
    Aug 7, 2012
    Posts:
    67
    What is the target? where is it set?

    Code (CSharp):
    1.     private void OnEnable()
    2.     {
    3.         lootTable = (LootTable)target;
    4.     }
     
  8. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    So, update, I tried out the following changes:

    Code (CSharp):
    1. ItemData itemData;
    2.     float odd;
    3.  
    4. itemData = (ItemData)EditorGUILayout.ObjectField("Loot: ", itemData, typeof(ItemData), false, GUILayout.Width(lootSize));
    5.         odd = EditorGUILayout.FloatField("Odds: ", odd, GUILayout.Width(oddsSize));
    And that works fine. I can put in my ItemData objects and my floats just fine, so the issue is with the array elements:

    Code (CSharp):
    1. int tableSize = 1;
    2. ItemData[] itemDatas;
    3.     float[] odds;
    4. tableSize = EditorGUILayout.IntField("Table Size:", tableSize);
    5. itemDatas = new ItemData[tableSize];
    6.         odds = new float[tableSize];
    7.  
    8. for (int i = 0; i < tableSize; i++)
    9.             {
    10.                 GUILayout.BeginHorizontal();
    11.  
    12.                 EditorGUIUtility.labelWidth = labelSize;
    13.                 itemDatas[i] = (ItemData) EditorGUILayout.ObjectField("Loot: ", itemDatas[i], typeof(ItemData), false, GUILayout.Width(lootSize));
    14.                 odds[i] = EditorGUILayout.FloatField("Odds: ", odds[i], GUILayout.Width(oddsSize));
    15.  
    16.                 GUILayout.EndHorizontal();
    17.             }
    For whatever reason, it doesn't work on the array elements, but it does work if I just put in the elements one by one. I really need to get the array working though.
     
  9. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Another update:

    I posted this question on Reddit and I figured out why the values were being reset based on the help there. The issue was this line:

    Code (CSharp):
    1. itemDatas = new ItemData[tableSize];
    2.         odds = new float[tableSize];
    Makes sense, it was making a new array each time.

    The issue now is that I can't seem to figure out a way to directly manipulate the size of these arrays. I tried switching to Lists and still got nowhere.

    I'm basically trying to recreate the default way lists and arrays work on the inspector, where you can type in a size, the array adjusts to that size, and then you can enter in values for each element. The key difference being that I'm trying to line up two elements from 2 arrays / lists.

    I feel like this should be doable, but I can't even figure out how to create that default functionality on a single array.