Search Unity

How to mske a contingent drop down lists in inspector?

Discussion in '2D' started by Timbon77, Oct 26, 2020.

  1. Timbon77

    Timbon77

    Joined:
    Oct 3, 2019
    Posts:
    38
    Hello everyone!

    I want to make 2 drop down lists that one is depended on the other.
    What I mean by that is that when I select one of the options from the first drop down, the variable in the second one willl change accordingly.
    An example that might help you get what I'm trying to implement:

    say I have two drop down lists in my inspector, the first one is 'class' and the second one is 'abilities'.
    If I choose a class name 'Elf' the second drop down will have the options: 'Archer, Healer'.
    and if I choose a class name 'Man' the second drop down will change its values to 'Thief, Warrior'

    I hope the idea is clear
     
  2. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
  3. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Easiest way to do this is to use serialized properties.

    First create a custom inspector.

    Then have fields for your values in your main class (not in the custom editor). Like one enum for character class and then one for elf options, thief options ... and so on for every character class.

    Then get those fields in your Custom Inspector as serialized properties.

    You can then render second field based on first enum selection... an if or a switch statement that renders elf options when elf is selected from first enum, thief options when thief is selected and so on...

    https://docs.unity3d.com/ScriptReference/SerializedObject.html
     
  4. Timbon77

    Timbon77

    Joined:
    Oct 3, 2019
    Posts:
    38
    Thanks for the comment I'll make sure to post in the right place next time, I managed to make somthing like this work only to find out that what I need is much more complicated.
    I have a scriptable object that I use for an array of variables, and I want to have the custom inspetor variables (Elf, Man) as one variable in the array, is there a way for me to add to the array the variable that I mentioned?

    Code (CSharp):
    1. [CreateAssetMenu(fileName = "New Players", menuName = "Players")]
    2. [System.Serializable]
    3. public class Map: ScriptableObject
    4. {
    5.     [System.Serializable]
    6.     public class Info
    7.     {
    8.           // Here I want to have the two drop down lists
    9.           public string Name;
    10.           public int Age;
    11.  
    12.      }
    13.  
    14.      public Info[]  PlayersList;
    15. }
     
  5. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @nazuben

    I'm really not sure what you want... maybe explain it in more detail.

    Anyway - you can create custom inspector for a Scriptable Object, but if you want to customize look of serializable class (not a MonoBehaviour), you'll have to use a Property Drawers.
     
  6. Timbon77

    Timbon77

    Joined:
    Oct 3, 2019
    Posts:
    38
    I have a scriptable object name 'Map' which is an array of variables (Name, Age) , I want to add to this array of variables another variable which is the two drop downs. Is there a way for me to create this customed inspector drop down and simply make a reference to it in the 'Map' scriptable object?

    maybe this example will make things more clear:

    let's say I have this scriptable object:

    Code (CSharp):
    1.     [CreateAssetMenu(fileName = "New Players", menuName = "Players")]
    2.     [System.Serializable]
    3.     public class Map: ScriptableObject
    4.     {
    5.         [System.Serializable]
    6.         public class Info
    7.         {
    8.               public string Name;
    9.               public int Age;
    10.          }
    11.          public Info[]  PlayersList;
    12.     }
    13.  
    And I create somewhere another class like so:

    Code (CSharp):
    1.  
    2.     public class MoreVariables
    3.     {
    4.         public int var1;
    5.         public int var2;
    6.     }
    7.  
    I then will be able to modify my scriptable object and use the new class:

    Code (CSharp):
    1.     [CreateAssetMenu(fileName = "New Players", menuName = "Players")]
    2.     [System.Serializable]
    3.     public class Map: ScriptableObject
    4.     {
    5.         [System.Serializable]
    6.         public class Info
    7.         {
    8.               public MoreVariables moreVars; // I want this line to be the lists
    9.               public string Name;
    10.               public int Age;
    11.          }
    12.          public Info[]  PlayersList;
    13.     }
    14.  
    Is there a way for me to make a reference to a Custom Inspector instead of the 'MoreVariables' class and in that way modify the scriptable object? or in other words, can I make the 'MoreVariables' a Custom Inspector?hopfuly without changing the values I have already created for 'Map's
     
  7. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    "Is there a way for me to make a reference to a Custom Inspector instead of the 'MoreVariables' class and in that way modify the scriptable object?"

    Custom Inspector is only rendering your data, you wouldn't reference it directly, you get the data from your MB or ScriptableObject class.

    "can I make the 'MoreVariables' a Custom Inspector?"

    You'll have to make it using PropertyDrawer most likely, if you want MoreVariables to be rendered that way everywhere in Editor.
     
    Last edited: Oct 27, 2020
  8. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    I'm not still quite sure what you mean by this:
    "// I want this line to be the lists"

    Do you actually mean you want this moreVars to be a dropdown?

    If that is the case, as you have data as separate int fields you'll have to build the dropdown yourself... collect the values into a list/array and then render that, with EditorGUILayout.Popup for example (of course you wouldn't have that default list rendered):

    blocks.gif

    But if you want to show some selection of values as a dropdown, I would use enums instead for that data. Then the rendering is automatic using EditorGUILayout.PropertyField.

    Anyway, it would be easier if you would show your Editor code you have so far.
     
    Last edited: Oct 27, 2020
  9. Timbon77

    Timbon77

    Joined:
    Oct 3, 2019
    Posts:
    38
    I don't have any Editor code that is what I'm trying to do now. If I understood you correctly I should just add all the enums that I want into the 'Map' and simply make them appear according to the selection?

    Code (CSharp):
    1.      [CreateAssetMenu(fileName = "New Players", menuName = "Players")]
    2.         [System.Serializable]
    3.         public class Map: ScriptableObject
    4.         {
    5.             [System.Serializable]
    6.             public class Info
    7.             {
    8.                   public enum player {Elf , Man};
    9.                   public player Player;
    10.  
    11.                  public enum powerElf {Healer,  Archer}
    12.                  public powerElf PowerElf;
    13.  
    14.                  public enum powerMan {Thief, Warrior};
    15.                  public powerMan PowerMan;
    16.  
    17.                   public string Name;
    18.                   public int Age;
    19.              }
    20.              public Info[]  PlayersList;
    21.         }
    Something like this? if so, how do I create the PropertyDrawer for this?
     
  10. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Last edited: Oct 27, 2020
  11. Timbon77

    Timbon77

    Joined:
    Oct 3, 2019
    Posts:
    38
    Hi again, so just to close this topic, I want to ask one final thing.
    I managed to get a few things working almost like I want them to, but I am still not sure how to make a modified list.

    Code (CSharp):
    1.  
    2. EditorGUI.Popup(rect1," ",index,options1);
    3.  
    4. EditorGUI.BeginChangeCheck();
    5. EditorGUI.Popup(rect2," ",index,options2);
    6.       if (EditorGUI.EndChangeCheck()) {
    7.             Debug.Log("Here you call a function");
    8.       }
    Here I have two popups, once I click the second one, I would like to be able to change the option list of the first popup(options1 vector).
    After I'm done with that I pretty much have all I need, is there a way for me to do that?