Search Unity

Draw Inspector within another Inspector

Discussion in 'UI Toolkit' started by ayellowpaper, Dec 2, 2019.

  1. ayellowpaper

    ayellowpaper

    Joined:
    Dec 8, 2013
    Posts:
    52
    Hey everyone,

    so while trying to draw an inspector within another inspector I almost decided to jump out of the window, but instead decided to post a thread. Maybe some Unity Dev or UI Guru can help me out. I'm on 2019.1.14f1.

    The TL;DR is: using InspectorElement doesn't create PropertyFields, but instead they are empty. See this image:


    The detailed version: I created a few simple scripts to test how to do it. The premise is simple: Draw the members from TestComponent2 in the Inspector of TestComponent1.
    Code (CSharp):
    1. public class TestComponent1 : MonoBehaviour
    2. {
    3.     public int TestValue1 = 15;
    4.     public TestComponent2 RefToComponent;
    5. }
    6.  
    Code (CSharp):
    1. public class TestComponent2 : MonoBehaviour
    2. {
    3.     public int TestValue2 = 55;  
    4. }
    I have then created a simple CustomEditor for TestComponent2:
    Code (CSharp):
    1. [CustomEditor(typeof(TestComponent2))]
    2. public class TestComponent2Editor : Editor
    3. {
    4.     public override VisualElement CreateInspectorGUI()
    5.     {
    6.         VisualElement root = new VisualElement();
    7.         root.Add(new PropertyField(serializedObject.FindProperty("TestValue2")));
    8.         return root;
    9.     }
    10. }
    So far so good because eerything works as intended. Now to the apparently tricky stuff: I want to display the above inspector in the inspector of TestComponent1.
    Code (CSharp):
    1. [CustomEditor(typeof(TestComponent1))]
    2. public class TestComponent1Editor : Editor
    3. {
    4.     public override VisualElement CreateInspectorGUI()
    5.     {
    6.         VisualElement root = new VisualElement();
    7.         var prop = serializedObject.FindProperty("RefToComponent");
    8.         root.Add(new PropertyField(serializedObject.FindProperty("TestValue1")));
    9.         root.Add(new PropertyField(prop));
    10.         if (prop.objectReferenceValue != null)
    11.             root.Add(new InspectorElement(prop.objectReferenceValue));
    12.         return root;
    13.     }
    14. }
    15.  
    The important bit is this line:
    root.Add(new InspectorElement(prop.objectReferenceValue));
    This innocent line actually doesn't really do anything. It creates the necessary elements but the PropertyField's are empty. There is nothing attached to it. How do I work around this issue?
     
  2. SevenSolaris

    SevenSolaris

    Joined:
    Jan 14, 2019
    Posts:
    20
    What I did was I got the Editor for the object with
    Code (CSharp):
    1. editor = Editor.CreateEditor(object)
    , then I check if it's a UIElements Inspector:
    Code (CSharp):
    1. var root = editor.CreateInspectorGUI()
    then you have to check if the root is null. If the root is null, that means that it doesn't use UI Elements, so you can create a new IMGUIContainer, and in onGUIHandler callback, call
    Code (CSharp):
    1. editor.OnInspectorGUI()
    .

    You might need to fiddle around with it to get it to work with what you're working with, but that should give you a good starting point. Oh, and if it is a UI Elements inspector, then you'll of course want to add the "root" to your container element.
     
    CyrilGhys likes this.
  3. ayellowpaper

    ayellowpaper

    Joined:
    Dec 8, 2013
    Posts:
    52
    Thank you for taking the time to respond. I've played around with it a bit but to no avail. Still comming up with empty property fields. Can you provide your working example for me to analyse?
     
  4. SevenSolaris

    SevenSolaris

    Joined:
    Jan 14, 2019
    Posts:
    20
    Oh, I see what your problem is. Your classes aren't serializable. You should be using the attribute System.Serializable.

    Aside from that, I believe that you should be using ScriptableObjects. If I remember correctly, it is inadvisable to just use a regular class.
     
  5. ayellowpaper

    ayellowpaper

    Joined:
    Dec 8, 2013
    Posts:
    52
    MonoBehaviours don't need the attribute System.Serializable because they are seriaizable by default. I don't use regular classes anywhere.
     
  6. SevenSolaris

    SevenSolaris

    Joined:
    Jan 14, 2019
    Posts:
    20
    Oh, my mistake. Could you share a screenshot of what your inspector looks like?
     
  7. matthew-holtzem

    matthew-holtzem

    Joined:
    Sep 1, 2016
    Posts:
    40