using System; using System.Collections.Generic; using System.Reflection; using UnityEngine; using Object = UnityEngine.Object; public static class ComponentExtensions { private static class ComponentsCache where TComponent : Component { public static readonly Dictionary components = new Dictionary(); } #if UNITY_EDITOR /// /// We need to cleanup each generic cache when domain reload is disabled. /// private static readonly Dictionary typesToCleanup = new Dictionary(); private static int reloadCounter; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void Init() { reloadCounter++; typesToCleanup.Clear(); } private static void CheckCacheCleanup() where TComponent : Component { if (reloadCounter > 0) { var componentType = typeof(TComponent); if (!typesToCleanup.TryGetValue(componentType, out var needsCleanup)) { typesToCleanup.Add(componentType, true); } if (needsCleanup) { ComponentsCache.components.Clear(); typesToCleanup[componentType] = false; } } } #endif public static bool TryGetComponentCached(this Component instance, out TComponent component) where TComponent : Component { return TryGetComponentCached(instance.gameObject, out component); } public static bool TryGetComponentCached(this GameObject gameObject, out TComponent component) where TComponent : Component { #if UNITY_EDITOR CheckCacheCleanup(); #endif if (ComponentsCache.components.TryGetValue(gameObject, out component)) return component; if (gameObject.TryGetComponent(out component)) ComponentsCache.components.Add(gameObject, component); return component; } public static TComponent GetComponentCached(this Component instance) where TComponent : Component { return GetComponentCached(instance); } public static TComponent GetComponentCached(this GameObject gameObject) where TComponent : Component { #if UNITY_EDITOR CheckCacheCleanup(); #endif if (ComponentsCache.components.TryGetValue(gameObject, out var component)) return component; if (gameObject.TryGetComponent(out component)) ComponentsCache.components.Add(gameObject, component); return component; } }