< 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:316
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
 157738        private readonly LinkedList<PoolableObject> unusedObjects = new LinkedList<PoolableObject>();
 157739        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
 157752        public Pool(string name, int maxPrewarmCount)
 53        {
 157754            if (PoolManager.USE_POOL_CONTAINERS)
 157755                container = new GameObject("Pool - " + name);
 56
 157757            this.maxPrewarmCount = maxPrewarmCount;
 157758        }
 59
 60        public void ForcePrewarm()
 61        {
 113962            if (maxPrewarmCount <= objectsCount)
 113963                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        public PoolableObject Get()
 73        {
 74            // These extra instantiations during initialization are to populate pools that will be used a lot later
 92175            if (PoolManager.i.initializing && !isInitialized)
 76            {
 47777                isInitialized = true;
 47778                int count = usedObjectsCount;
 79
 95480                for (int i = unusedObjectsCount; i < Mathf.Min(count * PREWARM_ACTIVE_MULTIPLIER, maxPrewarmCount); i++)
 81                {
 082                    Instantiate();
 83                }
 84
 47785                Instantiate();
 47786            }
 44487            else if (unusedObjects.Count == 0)
 88            {
 38189                Instantiate();
 90            }
 91
 92192            PoolableObject poolable = Extract();
 93
 92194            EnablePoolableObject(poolable);
 92195            poolable.OnPoolGet();
 92196            return poolable;
 97        }
 98
 99        private PoolableObject Extract()
 100        {
 921101            PoolableObject po = null;
 921102            po = unusedObjects.First.Value;
 921103            unusedObjects.RemoveFirst();
 921104            po.node = usedObjects.AddFirst(po);
 105
 106#if UNITY_EDITOR
 921107            RefreshName();
 108#endif
 921109            return po;
 110        }
 111
 112        public PoolableObject Instantiate()
 113        {
 858114            var gameObject = InstantiateAsOriginal();
 858115            return SetupPoolableObject(gameObject);
 116        }
 117
 118        public GameObject InstantiateAsOriginal()
 119        {
 880120            Assert.IsTrue(original != null, $"Original should never be null here ({id})");
 121
 880122            GameObject gameObject = null;
 123
 880124            if (instantiator != null)
 126125                gameObject = instantiator.Instantiate(original);
 126            else
 754127                gameObject = GameObject.Instantiate(original);
 128
 880129            gameObject.SetActive(true);
 130
 880131            return gameObject;
 132        }
 133
 134        private PoolableObject SetupPoolableObject(GameObject gameObject, bool active = false)
 135        {
 861136            if (PoolManager.i.poolables.ContainsKey(gameObject))
 0137                return PoolManager.i.GetPoolable(gameObject);
 138
 861139            PoolableObject poolable = new PoolableObject(this, gameObject);
 861140            PoolManager.i.poolables.Add(gameObject, poolable);
 861141            PoolManager.i.poolableValues.Add(poolable);
 142
 861143            if (!active)
 144            {
 858145                DisablePoolableObject(poolable);
 858146                poolable.node = unusedObjects.AddFirst(poolable);
 858147            }
 148            else
 149            {
 3150                EnablePoolableObject(poolable);
 3151                poolable.node = usedObjects.AddFirst(poolable);
 152            }
 153
 154#if UNITY_EDITOR
 861155            RefreshName();
 156#endif
 861157            return poolable;
 158        }
 159
 160        public void Release(PoolableObject poolable)
 161        {
 1383162            if (poolable == null || !PoolManager.i.HasPoolable(poolable))
 485163                return;
 164
 898165            DisablePoolableObject(poolable);
 166
 898167            poolable.node.List.Remove(poolable.node);
 898168            poolable.node = unusedObjects.AddFirst(poolable);
 169
 170#if UNITY_EDITOR
 898171            RefreshName();
 172#endif
 898173        }
 174
 175        public void ReleaseAll()
 176        {
 2664177            while (usedObjects.Count > 0)
 178            {
 711179                usedObjects.First.Value.Release();
 180            }
 1953181        }
 182
 183        /// <summary>
 184        /// This will add a gameObject that is not on any pool to this pool.
 185        /// </summary>
 186        /// <param name="gameObject"></param>
 187        public void AddToPool(GameObject gameObject, bool addActive = true)
 188        {
 3189            if (instantiator != null && !instantiator.IsValid(gameObject))
 190            {
 0191                Debug.LogError($"ERROR: Trying to add invalid gameObject to pool! -- {gameObject.name}", gameObject);
 0192                return;
 193            }
 194
 3195            PoolableObject obj = PoolManager.i.GetPoolable(gameObject);
 196
 3197            if (obj != null)
 198            {
 0199                Debug.LogError($"ERROR: gameObject is already being tracked by a pool! -- {gameObject.name}", gameObject
 0200                return;
 201            }
 202
 3203            SetupPoolableObject(gameObject, addActive);
 3204        }
 205
 206        public void RemoveFromPool(PoolableObject poolable)
 207        {
 5208            if (poolable.node != null)
 209            {
 5210                if (poolable.node.List != null)
 0211                    poolable.node.List.Remove(poolable);
 212
 5213                poolable.node = null;
 214            }
 215
 5216            PoolManager.i.poolables.Remove(poolable.gameObject);
 5217            PoolManager.i.poolableValues.Remove(poolable);
 218#if UNITY_EDITOR
 5219            RefreshName();
 220#endif
 5221        }
 222
 223        public void Cleanup()
 224        {
 1562225            ReleaseAll();
 226
 2396227            while (unusedObjects.Count > 0)
 228            {
 834229                PoolManager.i.poolables.Remove(unusedObjects.First.Value.gameObject);
 834230                PoolManager.i.poolableValues.Remove(unusedObjects.First.Value);
 834231                unusedObjects.RemoveFirst();
 232            }
 233
 1562234            while (usedObjects.Count > 0)
 235            {
 0236                PoolManager.i.poolables.Remove(usedObjects.First.Value.gameObject);
 0237                PoolManager.i.poolableValues.Remove(usedObjects.First.Value);
 0238                usedObjects.RemoveFirst();
 239            }
 240
 1562241            unusedObjects.Clear();
 1562242            usedObjects.Clear();
 243
 1562244            Object.Destroy(this.original);
 245
 1562246            if (PoolManager.USE_POOL_CONTAINERS)
 1562247                Object.Destroy(this.container);
 248
 1562249            OnCleanup?.Invoke(this);
 113250        }
 251
 252        public void EnablePoolableObject(PoolableObject poolable)
 253        {
 924254            GameObject go = poolable.gameObject;
 255
 924256            if (go == null)
 0257                return;
 258
 924259            if (!go.activeSelf)
 921260                go.SetActive(true);
 261
 924262            go.transform.ResetLocalTRS();
 263
 924264            lastGetTime = Time.unscaledTime;
 924265        }
 266
 267        public void DisablePoolableObject(PoolableObject poolable)
 268        {
 269#if UNITY_STANDALONE || UNITY_EDITOR
 1756270            if (DataStore.i.common.isApplicationQuitting.Get())
 0271                return;
 272#endif
 1756273            GameObject go = poolable.gameObject;
 274
 1756275            if (go == null)
 25276                return;
 277
 1731278            if (go.activeSelf)
 1729279                go.SetActive(false);
 280
 1731281            if (PoolManager.USE_POOL_CONTAINERS)
 282            {
 1731283                if (container != null)
 284                {
 1731285                    go.transform.SetParent(container.transform);
 286                }
 1731287            }
 288            else
 289            {
 0290                go.transform.SetParent(null);
 291            }
 0292        }
 293
 294#if UNITY_EDITOR
 295        private void RefreshName()
 296        {
 2685297            if (this.container != null)
 2685298                this.container.name = $"in: {unusedObjectsCount} out: {usedObjectsCount} id: {id} persistent: {persisten
 2685299        }
 300#endif
 301        public static bool FindPoolInGameObject(GameObject gameObject, out Pool pool)
 302        {
 3303            pool = null;
 304
 3305            if (PoolManager.i.poolables.TryGetValue(gameObject, out PoolableObject poolable))
 306            {
 0307                pool = poolable.pool;
 0308                return true;
 309            }
 310
 3311            return false;
 312        }
 313
 15314        public bool IsValid() { return original != null; }
 315    }
 316};