< Summary

Class:DCL.Pool
Assembly:PoolManager
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PoolManager/Pool.cs
Covered lines:107
Uncovered lines:24
Coverable lines:131
Total lines:320
Line coverage:81.6% (107 of 131)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Pool(...)0%220100%
ForcePrewarm()0%6.83025%
Get()0%5.065086.67%
Extract()0%110100%
Instantiate()0%110100%
InstantiateAsOriginal()0%220100%
SetupPoolableObject(...)0%33092.31%
Release(...)0%330100%
ReleaseAll()0%220100%
AddToPool(...)0%5.44055.56%
RemoveFromPool(...)0%3.023087.5%
Cleanup()0%5.165081.25%
EnablePoolableObject(...)0%3.023087.5%
DisablePoolableObject(...)0%6.446076.92%
RefreshName()0%220100%
FindPoolInGameObject(...)0%2.262060%
IsValid()0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/PoolManager/Pool.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4using DCL.Helpers;
 5using UnityEngine.Assertions;
 6
 7namespace DCL
 8{
 9    public interface IPooledObjectInstantiator
 10    {
 11        bool IsValid(GameObject original);
 12        GameObject Instantiate(GameObject gameObject);
 13    }
 14
 15    public class Pool : ICleanable
 16    {
 17        public delegate void OnReleaseAllDlg(Pool pool);
 18
 19        public const int PREWARM_ACTIVE_MULTIPLIER = 2;
 20        public object id;
 21        public GameObject original;
 22        public GameObject container;
 23
 24        public bool persistent = false;
 25
 26        /// <summary>
 27        /// If this is set to true, all Unity components in the poolable gameObject implementing ILifecycleHandler
 28        /// will be registered and called when necessary.
 29        ///
 30        /// The interface call responsibility lies in the PoolableObject class.
 31        /// </summary>
 32        public bool useLifecycleHandlers = false;
 33
 34        public System.Action<Pool> OnCleanup;
 35
 36        public IPooledObjectInstantiator instantiator;
 37
 161838        private readonly LinkedList<PoolableObject> unusedObjects = new LinkedList<PoolableObject>();
 161839        private readonly LinkedList<PoolableObject> usedObjects = new LinkedList<PoolableObject>();
 40
 41        private int maxPrewarmCount = 0;
 42        private bool isInitialized;
 43
 044        public float lastGetTime { get; private set; }
 45
 046        public int objectsCount => unusedObjectsCount + usedObjectsCount;
 47
 048        public int unusedObjectsCount { get { return unusedObjects.Count; } }
 49
 050        public int usedObjectsCount { get { return usedObjects.Count; } }
 51
 161852        public Pool(string name, int maxPrewarmCount)
 53        {
 161854            if (PoolManager.USE_POOL_CONTAINERS)
 161855                container = new GameObject("Pool - " + name);
 56
 161857            this.maxPrewarmCount = maxPrewarmCount;
 161858        }
 59
 60        public void ForcePrewarm()
 61        {
 116962            if (maxPrewarmCount <= objectsCount)
 116963                return;
 64
 065            int objectsToInstantiate = Mathf.Max(0, maxPrewarmCount - objectsCount);
 066            for (int i = 0; i < objectsToInstantiate; i++)
 67            {
 068                Instantiate();
 69            }
 070        }
 71
 72        /// <summary>
 73        /// This will return an instance of the poolable object
 74        /// </summary>
 75        /// <returns></returns>
 76        public PoolableObject Get()
 77        {
 78            // These extra instantiations during initialization are to populate pools that will be used a lot later
 183579            if (PoolManager.i.initializing && !isInitialized)
 80            {
 53881                isInitialized = true;
 53882                int count = usedObjectsCount;
 83
 107684                for (int i = unusedObjectsCount; i < Mathf.Min(count * PREWARM_ACTIVE_MULTIPLIER, maxPrewarmCount); i++)
 85                {
 086                    Instantiate();
 87                }
 88
 53889                Instantiate();
 53890            }
 129791            else if (unusedObjects.Count == 0)
 92            {
 123493                Instantiate();
 94            }
 95
 183596            PoolableObject poolable = Extract();
 97
 183598            EnablePoolableObject(poolable);
 183599            poolable.OnPoolGet();
 1835100            return poolable;
 101        }
 102
 103        private PoolableObject Extract()
 104        {
 1835105            PoolableObject po = null;
 1835106            po = unusedObjects.First.Value;
 1835107            unusedObjects.RemoveFirst();
 1835108            po.node = usedObjects.AddFirst(po);
 109
 110#if UNITY_EDITOR
 1835111            RefreshName();
 112#endif
 1835113            return po;
 114        }
 115
 116        public PoolableObject Instantiate()
 117        {
 1772118            var gameObject = InstantiateAsOriginal();
 1772119            return SetupPoolableObject(gameObject);
 120        }
 121
 122        public GameObject InstantiateAsOriginal()
 123        {
 1794124            Assert.IsTrue(original != null, $"Original should never be null here ({id})");
 125
 1794126            GameObject gameObject = null;
 127
 1794128            if (instantiator != null)
 131129                gameObject = instantiator.Instantiate(original);
 130            else
 1663131                gameObject = GameObject.Instantiate(original);
 132
 1794133            gameObject.SetActive(true);
 134
 1794135            return gameObject;
 136        }
 137
 138        private PoolableObject SetupPoolableObject(GameObject gameObject, bool active = false)
 139        {
 1775140            if (PoolManager.i.poolables.ContainsKey(gameObject))
 0141                return PoolManager.i.GetPoolable(gameObject);
 142
 1775143            PoolableObject poolable = new PoolableObject(this, gameObject);
 1775144            PoolManager.i.poolables.Add(gameObject, poolable);
 1775145            PoolManager.i.poolableValues.Add(poolable);
 146
 1775147            if (!active)
 148            {
 1772149                DisablePoolableObject(poolable);
 1772150                poolable.node = unusedObjects.AddFirst(poolable);
 1772151            }
 152            else
 153            {
 3154                EnablePoolableObject(poolable);
 3155                poolable.node = usedObjects.AddFirst(poolable);
 156            }
 157
 158#if UNITY_EDITOR
 1775159            RefreshName();
 160#endif
 1775161            return poolable;
 162        }
 163
 164        public void Release(PoolableObject poolable)
 165        {
 2299166            if (poolable == null || !PoolManager.i.HasPoolable(poolable))
 487167                return;
 168
 1812169            DisablePoolableObject(poolable);
 170
 1812171            poolable.node.List.Remove(poolable.node);
 1812172            poolable.node = unusedObjects.AddFirst(poolable);
 173
 174#if UNITY_EDITOR
 1812175            RefreshName();
 176#endif
 1812177        }
 178
 179        public void ReleaseAll()
 180        {
 3500181            while (usedObjects.Count > 0)
 182            {
 1630183                usedObjects.First.Value.Release();
 184            }
 1870185        }
 186
 187        /// <summary>
 188        /// This will add a gameObject that is not on any pool to this pool.
 189        /// </summary>
 190        /// <param name="gameObject"></param>
 191        public void AddToPool(GameObject gameObject, bool addActive = true)
 192        {
 3193            if (instantiator != null && !instantiator.IsValid(gameObject))
 194            {
 0195                Debug.LogError($"ERROR: Trying to add invalid gameObject to pool! -- {gameObject.name}", gameObject);
 0196                return;
 197            }
 198
 3199            PoolableObject obj = PoolManager.i.GetPoolable(gameObject);
 200
 3201            if (obj != null)
 202            {
 0203                Debug.LogError($"ERROR: gameObject is already being tracked by a pool! -- {gameObject.name}", gameObject
 0204                return;
 205            }
 206
 3207            SetupPoolableObject(gameObject, addActive);
 3208        }
 209
 210        public void RemoveFromPool(PoolableObject poolable)
 211        {
 5212            if (poolable.node != null)
 213            {
 5214                if (poolable.node.List != null)
 0215                    poolable.node.List.Remove(poolable);
 216
 5217                poolable.node = null;
 218            }
 219
 5220            PoolManager.i.poolables.Remove(poolable.gameObject);
 5221            PoolManager.i.poolableValues.Remove(poolable);
 222#if UNITY_EDITOR
 5223            RefreshName();
 224#endif
 5225        }
 226
 227        public void Cleanup()
 228        {
 1603229            ReleaseAll();
 230
 3351231            while (unusedObjects.Count > 0)
 232            {
 1748233                PoolManager.i.poolables.Remove(unusedObjects.First.Value.gameObject);
 1748234                PoolManager.i.poolableValues.Remove(unusedObjects.First.Value);
 1748235                unusedObjects.RemoveFirst();
 236            }
 237
 1603238            while (usedObjects.Count > 0)
 239            {
 0240                PoolManager.i.poolables.Remove(usedObjects.First.Value.gameObject);
 0241                PoolManager.i.poolableValues.Remove(usedObjects.First.Value);
 0242                usedObjects.RemoveFirst();
 243            }
 244
 1603245            unusedObjects.Clear();
 1603246            usedObjects.Clear();
 247
 1603248            Object.Destroy(this.original);
 249
 1603250            if (PoolManager.USE_POOL_CONTAINERS)
 1603251                Object.Destroy(this.container);
 252
 1603253            OnCleanup?.Invoke(this);
 118254        }
 255
 256        public void EnablePoolableObject(PoolableObject poolable)
 257        {
 1838258            GameObject go = poolable.gameObject;
 259
 1838260            if (go == null)
 0261                return;
 262
 1838263            if (!go.activeSelf)
 1835264                go.SetActive(true);
 265
 1838266            go.transform.ResetLocalTRS();
 267
 1838268            lastGetTime = Time.unscaledTime;
 1838269        }
 270
 271        public void DisablePoolableObject(PoolableObject poolable)
 272        {
 273#if UNITY_STANDALONE || UNITY_EDITOR
 3584274            if (DataStore.i.common.isApplicationQuitting.Get())
 0275                return;
 276#endif
 3584277            GameObject go = poolable.gameObject;
 278
 3584279            if (go == null)
 25280                return;
 281
 3559282            if (go.activeSelf)
 3557283                go.SetActive(false);
 284
 3559285            if (PoolManager.USE_POOL_CONTAINERS)
 286            {
 3559287                if (container != null)
 288                {
 3559289                    go.transform.SetParent(container.transform);
 290                }
 3559291            }
 292            else
 293            {
 0294                go.transform.SetParent(null);
 295            }
 0296        }
 297
 298#if UNITY_EDITOR
 299        private void RefreshName()
 300        {
 5427301            if (this.container != null)
 5427302                this.container.name = $"in: {unusedObjectsCount} out: {usedObjectsCount} id: {id} persistent: {persisten
 5427303        }
 304#endif
 305        public static bool FindPoolInGameObject(GameObject gameObject, out Pool pool)
 306        {
 3307            pool = null;
 308
 3309            if (PoolManager.i.poolables.TryGetValue(gameObject, out PoolableObject poolable))
 310            {
 0311                pool = poolable.pool;
 0312                return true;
 313            }
 314
 3315            return false;
 316        }
 317
 15318        public bool IsValid() { return original != null; }
 319    }
 320};