using System.Collections.Generic; using UnityEngine; namespace HighlightPlus { [ExecuteAlways] [DefaultExecutionOrder(-100)] public class HighlightLabelPoolManager : MonoBehaviour { private static HighlightLabelPoolManager instance; private static readonly Dictionary> labelPools = new Dictionary>(); private static readonly HashSet activeLabels = new HashSet(); private static readonly int initialPoolSize = 5; const string LABEL_INSTANCE_NAME = "Highlight Plus Label"; const string LABEL_POOL_NAME = "Highlight Plus Label Pool Manager"; [RuntimeInitializeOnLoadMethod] static void DomainReloadDisabledSupport () { DestroySceneLabels(); } void OnEnable () { if (instance == null) { instance = this; } else if (instance != this) { DestroyImmediate(gameObject); } ClearPools(); } void OnDestroy () { if (instance == this) { instance = null; } labelPools.Clear(); activeLabels.Clear(); } public static void DestroySceneLabels () { if (instance != null) { DestroyImmediate(instance.gameObject); instance = null; } ClearPools(); } static void ClearPools () { if (instance != null) { for (int i = instance.transform.childCount - 1; i >= 0; i--) { Transform child = instance.transform.GetChild(i); if (child != null) { DestroyImmediate(child.gameObject); } } } labelPools.Clear(); activeLabels.Clear(); } private static void InitializePool (GameObject prefab) { if (!labelPools.ContainsKey(prefab)) { labelPools[prefab] = new Queue(); for (int i = 0; i < initialPoolSize; i++) { CreatePooledLabel(prefab); } } } private static HighlightLabel CreatePooledLabel (GameObject prefab) { GameObject labelInstanceGO = Instantiate(prefab); labelInstanceGO.name = LABEL_INSTANCE_NAME; labelInstanceGO.hideFlags = HideFlags.DontSave; labelInstanceGO.transform.SetParent(instance.transform, false); HighlightLabel labelInstance = labelInstanceGO.GetComponentInChildren(); labelInstance.labelPrefab = prefab; labelInstance.isPooled = true; labelInstanceGO.SetActive(false); labelPools[prefab].Enqueue(labelInstance); return labelInstance; } public static HighlightLabel GetLabelInstance (GameObject prefab) { if (instance == null) { GameObject go = new GameObject(LABEL_POOL_NAME); go.hideFlags = HideFlags.DontSave; instance = go.AddComponent(); } // Initialize pool if needed InitializePool(prefab); // Try to get from pool HighlightLabel labelInstance = null; while (labelInstance == null && labelPools[prefab].Count > 0) { labelInstance = labelPools[prefab].Dequeue(); } if (labelInstance != null) { activeLabels.Add(labelInstance); return labelInstance; } // Create new instance if pool is empty HighlightLabel newLabel = CreatePooledLabel(prefab); activeLabels.Add(newLabel); return newLabel; } public static void ReturnToPool (HighlightLabel label) { if (label.labelPrefab != null && labelPools.ContainsKey(label.labelPrefab)) { labelPools[label.labelPrefab].Enqueue(label); activeLabels.Remove(label); } } public static void Refresh () { if (instance == null) return; instance.LateUpdate(); } void LateUpdate () { foreach (var label in activeLabels) { if (label == null) continue; if (label.isVisible) { label.UpdatePosition(); if (!label.gameObject.activeSelf) { label.gameObject.SetActive(true); } } } } } }