< 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
 160138        private readonly LinkedList<PoolableObject> unusedObjects = new LinkedList<PoolableObject>();
 160139        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
 160152        public Pool(string name, int maxPrewarmCount)
 53        {
 160154            if (PoolManager.USE_POOL_CONTAINERS)
 160155                container = new GameObject("Pool - " + name);
 56
 160157            this.maxPrewarmCount = maxPrewarmCount;
 160158        }
 59
 60        public void ForcePrewarm()
 61        {
 115162            if (maxPrewarmCount <= objectsCount)
 115163                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
 92975            if (PoolManager.i.initializing && !isInitialized)
 76            {
 48877                isInitialized = true;
 48878                int count = usedObjectsCount;
 79
 97680                for (int i = unusedObjectsCount; i < Mathf.Min(count * PREWARM_ACTIVE_MULTIPLIER, maxPrewarmCount); i++)
 81                {
 082                    Instantiate();
 83                }
 84
 48885                Instantiate();
 48886            }
 44187            else if (unusedObjects.Count == 0)
 88            {
 37889                Instantiate();
 90            }
 91
 92992            PoolableObject poolable = Extract();
 93
 92994            EnablePoolableObject(poolable);
 92995            poolable.OnPoolGet();
 92996            return poolable;
 97        }
 98
 99        private PoolableObject Extract()
 100        {
 929101            PoolableObject po = null;
 929102            po = unusedObjects.First.Value;
 929103            unusedObjects.RemoveFirst();
 929104            po.node = usedObjects.AddFirst(po);
 105
 106#if UNITY_EDITOR
 929107            RefreshName();
 108#endif
 929109            return po;
 110        }
 111
 112        public PoolableObject Instantiate()
 113        {
 866114            var gameObject = InstantiateAsOriginal();
 866115            return SetupPoolableObject(gameObject);
 116        }
 117
 118        public GameObject InstantiateAsOriginal()
 119        {
 888120            Assert.IsTrue(original != null, $"Original should never be null here ({id})");
 121
 888122            GameObject gameObject = null;
 123
 888124            if (instantiator != null)
 131125                gameObject = instantiator.Instantiate(original);
 126            else
 757127                gameObject = GameObject.Instantiate(original);
 128
 888129            gameObject.SetActive(true);
 130
 888131            return gameObject;
 132        }
 133
 134        private PoolableObject SetupPoolableObject(GameObject gameObject, bool active = false)
 135        {
 869136            if (PoolManager.i.poolables.ContainsKey(gameObject))
 0137                return PoolManager.i.GetPoolable(gameObject);
 138
 869139            PoolableObject poolable = new PoolableObject(this, gameObject);
 869140            PoolManager.i.poolables.Add(gameObject, poolable);
 869141            PoolManager.i.poolableValues.Add(poolable);
 142
 869143            if (!active)
 144            {
 866145                DisablePoolableObject(poolable);
 866146                poolable.node = unusedObjects.AddFirst(poolable);
 866147            }
 148            else
 149            {
 3150                EnablePoolableObject(poolable);
 3151                poolable.node = usedObjects.AddFirst(poolable);
 152            }
 153
 154#if UNITY_EDITOR
 869155            RefreshName();
 156#endif
 869157            return poolable;
 158        }
 159
 160        public void Release(PoolableObject poolable)
 161        {
 1400162            if (poolable == null || !PoolManager.i.HasPoolable(poolable))
 494163                return;
 164
 906165            DisablePoolableObject(poolable);
 166
 906167            poolable.node.List.Remove(poolable.node);
 906168            poolable.node = unusedObjects.AddFirst(poolable);
 169
 170#if UNITY_EDITOR
 906171            RefreshName();
 172#endif
 906173        }
 174
 175        public void ReleaseAll()
 176        {
 2702177            while (usedObjects.Count > 0)
 178            {
 725179                usedObjects.First.Value.Release();
 180            }
 1977181        }
 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        {
 1586225            ReleaseAll();
 226
 2428227            while (unusedObjects.Count > 0)
 228            {
 842229                PoolManager.i.poolables.Remove(unusedObjects.First.Value.gameObject);
 842230                PoolManager.i.poolableValues.Remove(unusedObjects.First.Value);
 842231                unusedObjects.RemoveFirst();
 232            }
 233
 1586234            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
 1586241            unusedObjects.Clear();
 1586242            usedObjects.Clear();
 243
 1586244            Object.Destroy(this.original);
 245
 1586246            if (PoolManager.USE_POOL_CONTAINERS)
 1586247                Object.Destroy(this.container);
 248
 1586249            OnCleanup?.Invoke(this);
 118250        }
 251
 252        public void EnablePoolableObject(PoolableObject poolable)
 253        {
 932254            GameObject go = poolable.gameObject;
 255
 932256            if (go == null)
 0257                return;
 258
 932259            if (!go.activeSelf)
 929260                go.SetActive(true);
 261
 932262            go.transform.ResetLocalTRS();
 263
 932264            lastGetTime = Time.unscaledTime;
 932265        }
 266
 267        public void DisablePoolableObject(PoolableObject poolable)
 268        {
 269#if UNITY_STANDALONE || UNITY_EDITOR
 1772270            if (DataStore.i.common.isApplicationQuitting.Get())
 0271                return;
 272#endif
 1772273            GameObject go = poolable.gameObject;
 274
 1772275            if (go == null)
 25276                return;
 277
 1747278            if (go.activeSelf)
 1745279                go.SetActive(false);
 280
 1747281            if (PoolManager.USE_POOL_CONTAINERS)
 282            {
 1747283                if (container != null)
 284                {
 1747285                    go.transform.SetParent(container.transform);
 286                }
 1747287            }
 288            else
 289            {
 0290                go.transform.SetParent(null);
 291            }
 0292        }
 293
 294#if UNITY_EDITOR
 295        private void RefreshName()
 296        {
 2709297            if (this.container != null)
 2709298                this.container.name = $"in: {unusedObjectsCount} out: {usedObjectsCount} id: {id} persistent: {persisten
 2709299        }
 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};