Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved UIToolkit (InspectorElement) does not draw content of ScriptableObject correctly

Discussion in 'UI Toolkit' started by CxydaIO, Jul 4, 2021.

  1. CxydaIO

    CxydaIO

    Joined:
    May 12, 2014
    Posts:
    61
    Hi there, i have another question regarding UiToolkit. I have a bunch of different GameDesign data configs which hold my GD data, all data classes inherit from ScriptableObject class. The standard imgui inspector draws all fields of the class correctly. Now i wanted to build a nice UI with UiToolkit and render the fields of those ScriptableObjects to my UiToolkit window. For that i used the InspectorElement class and pass the scriptableObjects like so:

    Code (CSharp):
    1. var inspectorElement = new InspectorElement(GddLoader.GetToolDefinition(_selectedEntityType));
    And what i get is this:
    upload_2021-7-4_9-59-7.png

    it almost looks correct but Durability and EquipType is not rendered correctly, only the labels are there but not the values. Durability is of type int and EquipType is an enum of EquipmentType.

    Why is that ? The standard imgui inspector renders the ScriptableObject like this:

    upload_2021-7-4_10-2-38.png

    I'm using Unity2021.1.12f1

    Thanks for your help !
     
    Last edited: Jul 4, 2021
  2. CxydaIO

    CxydaIO

    Joined:
    May 12, 2014
    Posts:
    61
    Okay i didn't solve it but i found a workaround (thanks to google) here. The suggested code does not work 100% since it seems we need to Bind() the PropertyField as well after instantiating it. Afterwards it works like a charm.

    With this workaroud I walk over all SerializedProperties of the SerializedObject and draw a PropertyField for it. There is a special handling for Header and Space attributes since Unity does not support that out of the box.

    Here is the changed code:


    Code (CSharp):
    1.         private static VisualElement BuildInspectorProperties(SerializedObject obj)
    2.         {
    3.             VisualElement container = new VisualElement {name = obj.targetObject.name};
    4.          
    5.             SerializedProperty iterator = obj.GetIterator();
    6.             Type targetType = obj.targetObject.GetType();
    7.             List<MemberInfo> members = new List<MemberInfo>(targetType.GetMembers());
    8.  
    9.             if (!iterator.NextVisible(true)) return container;
    10.             do
    11.             {
    12.                 if (iterator.propertyPath == "m_Script" && obj.targetObject != null)
    13.                 {
    14.                     continue;
    15.                 }
    16.                 PropertyField propertyField = new PropertyField(iterator.Copy())
    17.                 {
    18.                     name = "PropertyField:" + iterator.propertyPath,
    19.                 };
    20.                 propertyField.Bind(iterator.serializedObject);
    21.  
    22.                 MemberInfo member = members.Find(x => x.Name == propertyField.bindingPath);
    23.                 if (member != null)
    24.                 {
    25.                     IEnumerable<Attribute> headers = member.GetCustomAttributes(typeof(HeaderAttribute));
    26.                     IEnumerable<Attribute> spaces = member.GetCustomAttributes(typeof(SpaceAttribute));
    27.                     foreach (Attribute x in headers)
    28.                     {
    29.                         HeaderAttribute actual = (HeaderAttribute) x;
    30.                         Label header = new Label { text = actual.header};
    31.                         header.style.unityFontStyleAndWeight = FontStyle.Bold;
    32.                         container.Add(new Label { text = " ", name = "Header Spacer"});
    33.                         container.Add(header);
    34.                     }
    35.                     foreach (Attribute unused in spaces)
    36.                     {
    37.                         container.Add(new Label { text = " " });
    38.                     }
    39.                 }
    40.  
    41.                 container.Add(propertyField);
    42.             }
    43.             while (iterator.NextVisible(false));
    44.  
    45.             return container;
    46.         }
    and when you call it with:
    Code (CSharp):
    1.                     ScriptableObject gameDesignConfig = _selectedEntityType.GroupDefinition(property);
    2.  
    3.                         var content = BuildInspectorProperties(new SerializedObject(gameDesignConfig));
    4.                         _root.Add(propContainer);
    5.  
    I get what I expect:
    upload_2021-7-6_16-55-21.png
     
    Last edited: Jul 6, 2021
    DoctorShinobi, LaneFox and a_p_u_r_o like this.