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