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. Dismiss Notice

How to collapse Hierarchy scene nodes via script?

Discussion in 'Scripting' started by Peter77, Dec 30, 2018.

  1. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,438
    A level consists of multiple scenes in our game. Whenever we open a level in the editor (during edit-mode), we load all scenes that belong to this level like shown in the code below:
    Code (CSharp):
    1. [MenuItem("Open Level/Park")]
    2. static void OpenParkPrototypeMenuItem()
    3. {
    4.     UnityEditor.SceneManagement.EditorSceneManager.OpenScene("game_park");
    5.  
    6.     foreach (var addtiveScenePath in new[] { "game_park_props", "game_park_vegetation", "game_park_grass", "game_park_audio", "game_park_skyline", "and so on..." })
    7.     {
    8.         UnityEditor.SceneManagement.EditorSceneManager.OpenScene(addtiveScenePath, UnityEditor.SceneManagement.OpenSceneMode.Additive);
    9.     }
    10. }
    All this works great.

    The annoying thing is that Unity always expands each scene in the Hierarchy after opening it with EditorSceneManager.OpenScene().

    When we open a level, we load like 10 additional scenes and then we need to collapse each of these scenes before we can actually get to the thing we want.

    Is there a scripting way to collapse scenes in the Hierarchy?
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,438
    After posting the question, I thought why not looking at Unity's source code and found the private "UnityEditor.SceneHierarchyWindow.ExpandTreeViewItem" method, which is basically doing what I need.

    With a bit of reflection magic, I'm now able to collapse scene nodes in the Hierarchy window through code. :)

    Here is the code I came up with, works with 2017_4 only, because they removed the method SearchableEditorWindow.ExpandTreeViewItem in 2018.3.

    Code (CSharp):
    1. static void ExpandSceneHierarchy(UnityEngine.SceneManagement.Scene scene, bool expand)
    2. {
    3. #if UNITY_2017_4
    4.    foreach (var wnd in Resources.FindObjectsOfTypeAll<SearchableEditorWindow>())
    5.    {
    6.        if (wnd.GetType().Name != "SceneHierarchyWindow")
    7.            continue;
    8.  
    9.        var method = wnd.GetType().GetMethod("ExpandTreeViewItem", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new[] { typeof(int), typeof(bool) }, null);
    10.        if (method == null)
    11.        {
    12.            Dbg.Error(wnd, "Could not find method 'UnityEditor.SceneHierarchyWindow.ExpandTreeViewItem(int, bool)'.");
    13.            return;
    14.        }
    15.  
    16.        var field = scene.GetType().GetField("m_Handle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    17.        if (field == null)
    18.        {
    19.            Dbg.Error(wnd, "Could not find field 'int UnityEngine.SceneManagement.Scene.m_Handle'.");
    20.            return;
    21.        }
    22.  
    23.        var sceneHandle = field.GetValue(scene);
    24.        method.Invoke(wnd, new System.Object[] { sceneHandle, expand });
    25.    }
    26. #endif
    27. }
    28.  
     
    WildStyle69 and rboerdijk like this.
  3. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    Thanks for posting this as we need it as well! It would be really nice if we could get a bool expand parameter added to OpenScene() since this gets pretty annoying.
     
  4. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Sorry for the necro, but this is somethign I need so bad right now.
    What can we do to get this work in Unity 2019.X or 2020.X ?
     
  5. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,184
    For 2020.1.11f a working version is:

    Code (CSharp):
    1. private static void SetExpanded(Scene scene, bool expand)
    2. {
    3.     foreach (var window in Resources.FindObjectsOfTypeAll<SearchableEditorWindow>())
    4.     {
    5.         if (window.GetType().Name != "SceneHierarchyWindow")
    6.             continue;
    7.  
    8.         var method = window.GetType().GetMethod("SetExpandedRecursive",
    9.             System.Reflection.BindingFlags.Public |
    10.             System.Reflection.BindingFlags.NonPublic |
    11.             System.Reflection.BindingFlags.Instance, null,
    12.             new[] { typeof(int), typeof(bool) }, null);
    13.  
    14.         if (method == null)
    15.         {
    16.             Debug.LogError(
    17.                 "Could not find method 'UnityEditor.SceneHierarchyWindow.SetExpandedRecursive(int, bool)'.");
    18.             return;
    19.         }
    20.  
    21.         var field = scene.GetType().GetField("m_Handle",
    22.             System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    23.  
    24.         if (field == null)
    25.         {
    26.             Debug.LogError("Could not find field 'int UnityEngine.SceneManagement.Scene.m_Handle'.");
    27.             return;
    28.         }
    29.  
    30.         var sceneHandle = field.GetValue(scene);
    31.         method.Invoke(window, new[] { sceneHandle, expand });
    32.     }
    33. }
     
  6. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    207
    This also seems to work in 2019.4.11f1, so presumedly it's good for 2019 LTS.
     
  7. usernameHed

    usernameHed

    Joined:
    Apr 5, 2016
    Posts:
    92
    is there any way to know if the scene is callapsed or not ?
     
  8. WildStyle69

    WildStyle69

    Joined:
    Jul 20, 2016
    Posts:
    317
    This is great, thanks for sharing the code here, all that contributed!

    // Wildstyle