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

Custom Inspectors With Many Fields

Discussion in 'Editor & General Support' started by TerabyteTim, Jun 8, 2017.

  1. TerabyteTim

    TerabyteTim

    Joined:
    Oct 20, 2011
    Posts:
    115
    So I'm working on a custom inspector that can have over 100 fields in it, and I've noticed the editor getting quite laggy. I'm looking for any tips to improve performance of large inspectors.

    I've compared performance between "EditorGUILayout.PropertyField()" and the direct forms (IntField(), TextField(), etc) and it seems like in general PropertyField() performs much more slowly than the directly declared field types. Is it generally the case that PropertyField performs more slowly for all types?

    My main question is how to improve performance when dealing with so many fields. With the above results I believe switching to directly declared IntFields, etc will run better. Is there anything else I could do?

    It seems like right now Unity draws all fields regardless of if they're actually in view of the inspector window or not. Is there an easy way to tell if a field is in view of the inspector?
     
  2. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,386
    If you're bothering to make custom inspectors then why not just organize the fields in foldouts?
     
    fffMalzbier likes this.
  3. TerabyteTim

    TerabyteTim

    Joined:
    Oct 20, 2011
    Posts:
    115
    I've done that, but that doesn't stop it from slowing down significantly when users have multiple foldouts open.
     
  4. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    Make a test case and profile the editor when it slowing down, so you can find out what's going on.
     
  5. TerabyteTim

    TerabyteTim

    Joined:
    Oct 20, 2011
    Posts:
    115
    I did a test case already of an array of 200 integers with the default inspector. The slowdowns are all coming from EditorGUILayout.PropertyField() according to the profiler. When I switch it to use IntField it runs about 30ms faster, and the biggest slowdown is still IntField.
     
    npatch likes this.
  6. TerabyteTim

    TerabyteTim

    Joined:
    Oct 20, 2011
    Posts:
    115
    So I managed to write some code to make the inspector only draw fields in currently in the view.
    Before that code my usage in the profiler was a peak of 153ms and an average of 68ms, after that code I'm getting a peak of 57ms and an average of 27ms. Much better!

    Can't share the full code, but the hardest part was getting the current scroll position of the inspector. You just use the result of this to check if the field is in view.
    Code (CSharp):
    1. private float GetInspectorScrollPos()
    2.     {
    3.         float scroll = curScroll;
    4.  
    5.         //Get currently focused window, or the window that the mouse is currently over
    6.         EditorWindow focus = EditorWindow.focusedWindow;
    7.  
    8.         //If either window is our inspector, get its current scroll position
    9.         if (focus.ToString().Contains("UnityEditor.InspectorWindow") || (focus = EditorWindow.mouseOverWindow).ToString().Contains("UnityEditor.InspectorWindow"))
    10.         {
    11.             System.Type T = System.Type.GetType("UnityEditor.InspectorWindow,UnityEditor");
    12.             if (T != null)
    13.                 scroll = ((Vector2)T.GetField("m_ScrollPosition").GetValue(focus)).y;
    14.         }
    15.  
    16.         return scroll;
    17.     }
     
  7. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    228
    I just reached the same conclusion. It kinda makes sense. I guess I never really thought about it. Even though it's super nice to just use it and handles calling the appropriate drawer or custom editor ,while also keeping the code cleaner, it's still a generic function. Generic functions are almost never performant.

    Another thing I noticed running a profiler on the editor is that a looooot of things generate garbage on the editor UI. And some things are beyond our reach, like some calls that retrieve Assembly fully qualified names.
     
  8. aka3eka

    aka3eka

    Joined:
    May 10, 2019
    Posts:
    32
    For those who need the code working in the newer versions of Unity (checked with 2019.2.19f1):

    Code (CSharp):
    1. public static bool IsOutOfScreen(Rect position)
    2.         {
    3.             float scrollPosition = 0;
    4.             float windowHeight = 0;
    5.             //Get currently focused window, or the window that the mouse is currently over
    6.             EditorWindow focus = EditorWindow.focusedWindow;
    7.             //If either window is our inspector, get its current scroll position
    8.             if (focus.ToString().Contains("UnityEditor.InspectorWindow") || (focus = EditorWindow.mouseOverWindow).ToString().Contains("UnityEditor.InspectorWindow"))
    9.             {
    10.                 System.Type T = System.Type.GetType("UnityEditor.InspectorWindow,UnityEditor");
    11.                 if (T != null)
    12.                 {
    13.                     ScrollView sv = (ScrollView)T.GetField("m_ScrollView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(focus);
    14.                     scrollPosition = sv.scrollOffset.y;
    15.                     windowHeight = sv.contentViewport.layout.height;
    16.                 }
    17.             }
    18.  
    19.             bool above = (position.y + position.height) < scrollPosition;
    20.             bool below = position.y > (scrollPosition + windowHeight);
    21.  
    22.             return above || below;
    23.         }
     
    adefilippis likes this.