Advertisement
Guest User

Untitled

a guest
Oct 21st, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.93 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement