SHARE
TWEET

Untitled

a guest Oct 21st, 2019 61 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define ENABLE_LOGGING // Logs the folder objects that were flattened to the console
  2. //#define SIMULATE_BUILD_BEHAVIOUR_ON_PLAY_MODE // Simulates Execution.AtBuildTime when entering Play Mode in the Editor, as well
  3.  
  4. #if UNITY_EDITOR
  5. using UnityEditor;
  6. using UnityEditor.Callbacks;
  7. using UnityEngine.SceneManagement;
  8. using System.Collections.Generic;
  9. using System.Reflection;
  10. #endif
  11. using UnityEngine;
  12.  
  13. [DisallowMultipleComponent]
  14. public class HierarchyFolderObject : MonoBehaviour
  15. {
  16.     public enum Execution
  17.     {
  18.         AtBuildTime = 0,
  19.         OnAwake = 1,
  20.         ViaScript = 2
  21.     };
  22.  
  23.     [Tooltip( "Determines whether detached child objects' GameObjects will be active or inactive" )]
  24.     public bool ChildrenActiveState = true;
  25.  
  26.     [Tooltip( "If less than or equal to 1: child objects will simply be unparented (detached)\n" +
  27.               "Otherwise: child objects will be split into groups of specified size and each group will be parented to an empty object at the root of the scene" )]
  28.     public int GroupSize = 0;
  29.  
  30.     [Tooltip( "Determines when the child objects are detached from this folder object\n\n" +
  31.               "AtBuildTime: While building the game, has no runtime overhead (objects instantiated at runtime will fallback to OnAwake)\n" +
  32.               "OnAwake: When the Awake function of this folder object is called at runtime\n" +
  33.               "ViaScript: When the Flatten() function of this folder object is called via a script" )]
  34.     public Execution ExecutionTime = Execution.ViaScript;
  35.  
  36.     private void Awake()
  37.     {
  38.         if( ExecutionTime != Execution.ViaScript )
  39.         {
  40. #if ENABLE_LOGGING
  41.             Debug.Log( string.Concat( "Flattened folder object at runtime: ", name ) );
  42. #endif
  43.  
  44.             Flatten();
  45.             Destroy( this );
  46.         }
  47.     }
  48.  
  49.     public void Flatten()
  50.     {
  51.         Transform tr = transform;
  52.         if( tr.childCount == 0 )
  53.             return;
  54.  
  55.         for( int i = tr.childCount - 1; i >= 0; i-- )
  56.             tr.GetChild( i ).gameObject.SetActive( ChildrenActiveState );
  57.  
  58.         if( GroupSize <= 1 )
  59.             tr.DetachChildren();
  60.         else
  61.         {
  62.             Transform parent = null;
  63.             for( int i = tr.childCount - 1, count = GroupSize; i >= 0; i-- )
  64.             {
  65.                 if( ++count > GroupSize )
  66.                 {
  67.                     parent = new GameObject().transform;
  68.                     count = 1;
  69.                 }
  70.  
  71.                 tr.GetChild( i ).SetParent( parent, true );
  72.             }
  73.         }
  74.     }
  75.  
  76. #if UNITY_EDITOR
  77.     [PostProcessScene( 2 )]
  78.     public static void OnPostprocessScene()
  79.     {
  80. #if !SIMULATE_BUILD_BEHAVIOUR_ON_PLAY_MODE
  81.         if( !BuildPipeline.isBuildingPlayer )
  82.             return;
  83. #endif
  84.  
  85.         Scene scene = SceneManager.GetActiveScene();
  86.         if( scene.isLoaded )
  87.         {
  88.             GameObject[] roots = scene.GetRootGameObjects();
  89.             for( int i = 0; i < roots.Length; i++ )
  90.                 FlattenFoldersRecursive( roots[i].transform );
  91.         }
  92.         else
  93.         {
  94.             // For some reason, the processed scene has its isLoaded flag set as false sometimes
  95.             // In this case, use reflection to call the GetRootGameObjectsInternal function directly
  96.             // (calling GetRootGameObjects when isLoaded is false throws an exception)
  97.             MethodInfo method = typeof( Scene ).GetMethod( "GetRootGameObjectsInternal", BindingFlags.Static | BindingFlags.NonPublic );
  98.             FieldInfo handle = typeof( Scene ).GetField( "m_Handle", BindingFlags.Instance | BindingFlags.NonPublic );
  99.  
  100.             List<GameObject> roots = new List<GameObject>( scene.rootCount );
  101.             method.Invoke( scene, new object[] { handle.GetValue( scene ), roots } );
  102.             for( int i = 0; i < roots.Count; i++ )
  103.                 FlattenFoldersRecursive( roots[i].transform );
  104.         }
  105.     }
  106.  
  107.     private static void FlattenFoldersRecursive( Transform obj )
  108.     {
  109.         for( int i = obj.childCount - 1; i >= 0; i-- )
  110.             FlattenFoldersRecursive( obj.GetChild( i ) );
  111.  
  112.         HierarchyFolderObject folderObject = obj.GetComponent<HierarchyFolderObject>();
  113.         if( folderObject && folderObject.ExecutionTime == Execution.AtBuildTime )
  114.         {
  115. #if ENABLE_LOGGING
  116.             Debug.Log( string.Concat( "Flattened folder object: ", obj.name, " (", obj.gameObject.scene.name, ")" ) );
  117. #endif
  118.  
  119.             folderObject.Flatten();
  120.             DestroyImmediate( folderObject );
  121.         }
  122.     }
  123.  
  124.     private void Reset()
  125.     {
  126.         ChildrenActiveState = gameObject.activeInHierarchy;
  127.         ExecutionTime = Execution.AtBuildTime;
  128.     }
  129. #endif
  130. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top