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

Feedback Folding/Unfolding gameObjects in hierarchy

Discussion in 'Scripting' started by saifshk17, Feb 25, 2021.

  1. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Hey everyone,

    I wrote few lines of an editor code that lets user to fold/unfold selected gameObjects in hierarchy. This only works if the Parent game Object is selected and you would like to expand the parent's children or collapse them all. Let me know what you think.

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. internal class CollapseExpand : EditorWindow {
    5.     private static void OnGUI (bool m) {
    6.         using (var scope = new EditorGUI.DisabledGroupScope (Selection.activeGameObject == null)) {
    7.            
    8.                 var type = typeof (EditorWindow).Assembly.GetType ("UnityEditor.SceneHierarchyWindow");
    9.                 var window = GetWindow (type);
    10.                 var exprec = type.GetMethod ("SetExpandedRecursive");
    11.                 exprec.Invoke (window, new object[] { Selection.activeGameObject.GetInstanceID (), m});    
    12.         }
    13.     }
    14.  
    15.     [MenuItem ("GameObject/Expand GameObjects", priority = 40)]
    16.     private static void ExpandGameObjects () {
    17.         bool i = true;
    18.         OnGUI (i);
    19.     }
    20.  
    21.     [MenuItem ("GameObject/Collapse GameObjects", priority = 40)]
    22.     private static void CollapseGameObjects () {
    23.         bool i = false;
    24.         OnGUI (i);
    25.     }
    26. }
     
  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,061
    Don't know about Windows but on macOS you can use the left/right arrows to fold/unfold and hold alt to do so recursively. This works all across Unity, wherever you have a tree view (hierarchy, project, inspector etc).

    I would expect the same/similar keys to work on Windows?
     
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,915
    Well I don't really see the point of this ^^. You can simply hold down ALT and press left / right arrow in the hierarchy to collapse / expand the selected gameobject(s).

    Though if you like to have menu items and want to use such an extension class, there are a few things you should change:

    • First of all, don't derive your class from EditorWindow if it's not an editor window. You can use MenuItems in any class.
    • OnGUI has a very specific meaning inside Unity. Do not call your method OnGUI if it does not draw IMGUI elements.
    • Common style guide: do not name a variable "i" that is not an integer.
    • For slight performance optimisation: You should lazy initialize and cache your window type in a static variable and you could also cache the MethodInfo as well as the parameters array. This will improve the speed and also get rid of "some" of the garbage allocations.
    Here's how I would have implemented this class:

    Code (CSharp):
    1. using UnityEditor;
    2. using System.Reflection;
    3.  
    4. internal static class CollapseExpand
    5. {
    6.     private static object[] m_ParametersExpand = new object[] { null, true };
    7.     private static object[] m_ParametersCollapse = new object[] { null, false };
    8.     private static System.Type m_SceneHierarchyWindowType = null;
    9.     private static System.Type SceneHierarchyWindowType
    10.     {
    11.         get
    12.         {
    13.             if (m_SceneHierarchyWindowType == null)
    14.             {
    15.                 var assembly = typeof(EditorWindow).Assembly;
    16.                 m_SceneHierarchyWindowType = assembly.GetType("UnityEditor.SceneHierarchyWindow");
    17.             }
    18.             return m_SceneHierarchyWindowType;
    19.         }
    20.     }
    21.     private static MethodInfo m_SetExpandedRecursive = null;
    22.     private static MethodInfo SetExpandedRecursiveImpl
    23.     {
    24.         get
    25.         {
    26.             if (m_SetExpandedRecursive == null)
    27.                 m_SetExpandedRecursive = m_SceneHierarchyWindowType.GetMethod("SetExpandedRecursive");
    28.             return m_SetExpandedRecursive;
    29.         }
    30.     }
    31.     private static void SetExpandedRecursive(int aInstanceID, bool aExpand)
    32.     {
    33.         var hierachyWindow = EditorWindow.GetWindow(SceneHierarchyWindowType);
    34.         if (aExpand)
    35.         {
    36.             m_ParametersExpand[0] = aInstanceID;
    37.             SetExpandedRecursiveImpl.Invoke(hierachyWindow, m_ParametersExpand);
    38.         }
    39.         else
    40.         {
    41.             m_ParametersCollapse[0] = aInstanceID;
    42.             SetExpandedRecursiveImpl.Invoke(hierachyWindow, m_ParametersCollapse);
    43.         }
    44.     }
    45.  
    46.     [MenuItem("CONTEXT/GameObject/Expand GameObjects")]
    47.     [MenuItem("GameObject/Expand GameObjects", priority = 40)]
    48.     private static void ExpandGameObjects()
    49.     {
    50.         SetExpandedRecursive(Selection.activeGameObject.GetInstanceID(), true);
    51.     }
    52.  
    53.     [MenuItem("CONTEXT/GameObject/Collapse GameObjects")]
    54.     [MenuItem("GameObject/Collapse GameObjects", priority = 40)]
    55.     private static void CollapseGameObjects()
    56.     {
    57.         SetExpandedRecursive(Selection.activeGameObject.GetInstanceID(), false);
    58.     }
    59.  
    60.     [MenuItem("GameObject/Expand GameObjects", validate = true)]
    61.     [MenuItem("GameObject/Collapse GameObjects", validate = true)]
    62.     private static bool CanExpandOrCollapse()
    63.     {
    64.         return Selection.activeGameObject != null;
    65.     }
    66. }
    67.  
    Note that I added the "validate" method for the two menuitems. Since the GameObject menu is kinda inconvenient I also added context menu items. So you can simply right click on a gameobject in the hierarchy view and select the two menu items there as well.

    I created two seperate parameters arrays since storing value types (integers, boolean values) in an object array will box the value and generate garbage. We can not avoid this for the instance ID but it's easy for the boolean parameter.
     
    Whatever560, rlofeudo and WidmerNoel like this.
  4. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Yes ofc but I wanted to achieve the same through scripting :)
     
  5. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Woah!! Thanks! That is much better than what I have implemented.
     
  6. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    Sorry to bring up an old thread, but does anyone happen to know if there is a way to prevent expanding parent objects upon selection in the first place? I am wanting to be able to select a massive amount of objects without expanding. Some sort of "silent" selection, for lack of a better term.

    I can select them and then try to issue a command to collapse the hierarchy after the fact, but unfortunately, it doesn't always work without invoking it multiple times. Depending on how many objects are selected, it seems to fire off before the actual selection has completed.
     
  7. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,525
    @MostHated You can prevent unfolding the parent(s) on selection by clicking the lock icon of the Hierarchy window (top right corner). With the lock, the folder open/close state only changes when you manually click the expand/collapse icons in the hierarchy.