Search Unity

Question How to refresh custom inspector when variable changed?

Discussion in 'UI Toolkit' started by Nit_Ram, Jun 7, 2023.

  1. Nit_Ram

    Nit_Ram

    Joined:
    May 8, 2016
    Posts:
    27
    Hello there!

    We just upgraded to the new Unity 2022.3.0 LTS for our new project and with this also to UIElements.
    We're now trying to create a custom inspector that draws either the default inspector or a label. Which one of these it should render is dependent of a bool inside the component.
    The problem is, that CreateInspectorGUI is only called once and not each time the view refreshes like the old OnGUI was. So when the bool changes, the custom inspector is not updated.
    We probably need to use binding in some way but ... how? It's not quite clear how it should be implemented.

    Here is pseudo code that explains what we're trying to achieve.

    Code (CSharp):
    1. [CustomEditor(typeof(MyComponent))]
    2. public class MyComponentInspector : Editor
    3. {
    4.     public override VisualElement CreateInspectorGUI()
    5.     {
    6.         var myComponent = target as MyComponent;
    7.  
    8.         //This if statement should be called when myComponent.myBool changed.
    9.         if(myComponent.myBool)
    10.         {
    11.             //draw the default inspector
    12.             return base.CreateInspectorGUI();
    13.         }
    14.         else
    15.         {
    16.             //render some label text
    17.         }
    18.     }
    19. }
     
    Last edited: Jun 7, 2023
  2. rawna

    rawna

    Joined:
    Aug 13, 2015
    Posts:
    35
    First of all, calling "base.CreateInspectorGUI()" will not show the default inspector. To do that you need to use
    "InspectorElement.FillDefaultInspector", like so
    Code (CSharp):
    1. var defaultInspector = new VisualElement();
    2. InspectorElement.FillDefaultInspector(defaultInspector, serializedObject, this);

    Now for the main question, you basically have to create both views, and then use
    "TrackPropertyValue" to show and hide the appropriate view.

    Here's some quick and dirty code that illustrates this.

    Code (CSharp):
    1. public override VisualElement CreateInspectorGUI()
    2. {
    3.     var container = new VisualElement();
    4.    
    5.     var defaultInspector = new VisualElement();
    6.     InspectorElement.FillDefaultInspector(defaultInspector, serializedObject, this);
    7.    
    8.     var labelText = new Label("Hello");
    9.    
    10.     container.Add(defaultInspector);
    11.     container.Add(labelText);
    12.    
    13.     var boolSerializedProperty = serializedObject.FindProperty("myBool");
    14.    
    15.     container.TrackPropertyValue(boolSerializedProperty, _ => {
    16.         var myBoolValue = boolSerializedProperty.boolValue;
    17.         if (myBoolValue) {
    18.            //show default inspector
    19.             defaultInspector.style.display = DisplayStyle.Flex;
    20.             labelText.style.display = DisplayStyle.None;
    21.         }
    22.         else {
    23.            //show label
    24.             defaultInspector.style.display = DisplayStyle.None;
    25.             labelText.style.display = DisplayStyle.Flex;
    26.         }
    27.     });
    28.     return container;
    29. }
     
    karl_jones likes this.
  3. Nit_Ram

    Nit_Ram

    Joined:
    May 8, 2016
    Posts:
    27
    Thank you for your answer, that helps a lot!

    One additional answer:
    We're working with serialized auto-properties like so. Are those supported by UIElements? Because when using FindProperty on it, it returns null. We even tried to get the backing field of the auto property, but that still returns null.

    Code (CSharp):
    1. [field: SerializeField]
    2. public bool MyBool { get; private set; }
     
    Last edited: Jun 8, 2023
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,923
    You need to get the backing field as the property itself isn't what's being drawn/serialised. I would look at the serialised data to determine the serialised property name, or find the field in the inspector and Right Click -> Copy Property Path.