Advertisement
SarahNorthway

EditorManager.cs

Jul 9th, 2017
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.67 KB | None | 0 0
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditor.SceneManagement;
  4.  
  5. /// <summary>
  6. /// Controls things that happen in the editor at every tick or when scene changes.
  7. /// Fix for crash when hitting run or unloading scene if a child is activeInHierarchy but some parent is !activeSelf.
  8. /// Issue #828408
  9. /// https://issuetracker.unity3d.com/issues/active-child-of-disabled-parent-crashes-editor-when-creating-new-scene
  10. /// </summary>
  11. ///
  12. [InitializeOnLoad]
  13. public class EditorManager {
  14.     private static double lastUpdateTime = -1;
  15.     private static float updateFrequencySeconds = 60f;
  16.     private static System.DateTime startTime = System.DateTime.UtcNow;
  17.     private static string currentScene;
  18.  
  19.     /// <summary>
  20.     /// Runs on Unity editor start, on compile, and on play in editor.
  21.     /// </summary>
  22.     static EditorManager() {
  23.         // fix after scene changes (crash still occurs when leaving buggy scene)
  24.         EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
  25.  
  26.         // and when hitting play before crash would occur
  27.         EditorApplication.playmodeStateChanged += FixInvalidActiveChildren;
  28.  
  29.         // and once a minute for good measure
  30.         EditorApplication.update += Update;
  31.     }
  32.  
  33.     /// <summary>
  34.     /// Runs every frame while in edit mode and in play mode while in editor.
  35.     /// Runs more often and reliably than Update on MonoBehaviors with [ExecuteInEditMode]
  36.     /// </summary>
  37.     static void Update() {
  38.         if (!isUnityEditMode) return;
  39.  
  40.         // perform check every minute
  41.         double currentTime = (System.DateTime.UtcNow - startTime).TotalSeconds;
  42.         if (currentTime > lastUpdateTime + updateFrequencySeconds) {
  43.             lastUpdateTime = currentTime;
  44.             FixInvalidActiveChildren();
  45.         }
  46.     }
  47.  
  48.     /// <summary>
  49.     /// When object created, renamed, moved or destroyed in scene hierarchy,
  50.     /// including when scene changes and on compile.
  51.     /// </summary>
  52.     static void HierarchyWindowChanged() {
  53.         if (!isUnityEditMode) return;
  54.  
  55.         // scene changed
  56.         if (currentScene != EditorSceneManager.GetActiveScene().path) {
  57.             currentScene = EditorSceneManager.GetActiveScene().path;
  58.             FixInvalidActiveChildren();
  59.         }
  60.     }
  61.  
  62.     /// <summary>
  63.     /// Runs once a minute while in edit mode.
  64.     /// </summary>
  65.     static void FixInvalidActiveChildren() {
  66.         GameObject[] parents = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
  67.         foreach (GameObject parent in parents) {
  68.             GameObject invalidActiveChild = FindInvalidActiveChild(parent, !parent.activeSelf);
  69.             if (invalidActiveChild != null) {
  70.                 Debug.LogWarning("EditorBugFixer found invalid active child, fixing... " + invalidActiveChild.GetPath());
  71.                 // twiddle root parent activeSelf to force child to become !activeInHierarchy
  72.                 bool parentWasActive = parent.activeSelf;
  73.                 parent.SetActive(false);
  74.                 parent.SetActive(true);
  75.                 parent.SetActive(false);
  76.                 parent.SetActive(parentWasActive);
  77.             }
  78.         }
  79.     }
  80.  
  81.     static GameObject FindInvalidActiveChild(GameObject parent, bool someParentInactive) {
  82.         foreach (Transform child in parent.transform) {
  83.             if (someParentInactive && child.gameObject.activeInHierarchy) {
  84.                 // only need one per root, twiddling root should fix any others
  85.                 return child.gameObject;
  86.             } else {
  87.                 bool someInactive = someParentInactive || !child.gameObject.activeSelf;
  88.                 GameObject invalidGrandchild = FindInvalidActiveChild(child.gameObject, someInactive);
  89.                 if (invalidGrandchild != null) {
  90.                     return invalidGrandchild;
  91.                 }
  92.             }
  93.         }
  94.         return null;
  95.     }
  96.    
  97.     /// <summary>
  98.     /// Are we in the editor and not playing?
  99.     /// </summary>
  100.     public static bool isUnityEditMode {
  101.         get {
  102. #if UNITY_EDITOR
  103.         if (!UnityEditor.EditorApplication.isPlaying) return true;
  104. #endif
  105.         return false;
  106.         }
  107.     }
  108. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement