< Summary

Class:DCL.AssetBundlesLoader
Assembly:AssetPromiseKeeper
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB/AssetBundlesLoader.cs
Covered lines:73
Uncovered lines:16
Coverable lines:89
Total lines:225
Line coverage:82% (73 of 89)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AssetBundleInfo(...)0%110100%
AssetBundlesLoader()0%110100%
Start()0%220100%
Stop()0%6200%
MarkAssetBundleForLoad(...)0%220100%
LoadAssetBundlesCoroutine()0%12.2812087.5%
LoadAssetBundle()0%19.7719087.1%
IsLoadBudgetTimeReached(...)0%330100%
WaitForSkippedFrames()0%440100%
CheckForReprioritizeAwaitingAssets()0%12.415033.33%
GetDistanceFromPlayer(...)0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB/AssetBundlesLoader.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Linq;
 5using UnityEngine;
 6
 7namespace DCL
 8{
 9    public class AssetBundlesLoader
 10    {
 11        private const float MAX_LOAD_BUDGET_TIME = 0.05f;
 12        private const int SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_NEARBY_ASSETS = 1;
 13        private const int SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_DISTANT_ASSETS = 5;
 14        private const float MAX_SQR_DISTANCE_FOR_QUICK_LOADING = 6000f;
 15        private const float TIME_BETWEEN_REPRIORITIZATIONS = 1f;
 16
 17        private struct AssetBundleInfo
 18        {
 19            public Asset_AB asset;
 20            public AssetBundle assetBundle;
 21            public Transform containerTransform;
 22            public Action onSuccess;
 23            public Action onFail;
 24
 25            public AssetBundleInfo(Asset_AB asset, AssetBundle assetBundle, Transform containerTransform, Action onSucce
 26            {
 1727                this.asset = asset;
 1728                this.assetBundle = assetBundle;
 1729                this.containerTransform = containerTransform;
 1730                this.onSuccess = onSuccess;
 1731                this.onFail = onFail;
 1732            }
 33        }
 34
 35        private Coroutine assetBundlesLoadingCoroutine;
 136        private Queue<AssetBundleInfo> highPriorityLoadQueue = new Queue<AssetBundleInfo>();
 137        private Queue<AssetBundleInfo> lowPriorityLoadQueue = new Queue<AssetBundleInfo>();
 38
 139        private Dictionary<string, int> loadOrderByExtension = new Dictionary<string, int>()
 40        {
 41            { "png", 0 },
 42            { "jpg", 1 },
 43            { "peg", 2 },
 44            { "bmp", 3 },
 45            { "psd", 4 },
 46            { "iff", 5 },
 47            { "mat", 6 },
 48            { "nim", 7 },
 49            { "ltf", 8 },
 50            { "glb", 9 }
 51        };
 52
 153        private List<UnityEngine.Object> loadedAssetsByName = new List<UnityEngine.Object>();
 54        private float currentLoadBudgetTime = 0;
 55        private AssetBundleInfo assetBundleInfoToLoad;
 56        private float lastQueuesReprioritizationTime = 0;
 57
 3058        private bool limitTimeBudget => CommonScriptableObjects.rendererState.Get();
 59
 60        public void Start()
 61        {
 3562            if (assetBundlesLoadingCoroutine != null)
 3463                return;
 64
 165            assetBundlesLoadingCoroutine = CoroutineStarter.Start(LoadAssetBundlesCoroutine());
 166        }
 67
 68        public void Stop()
 69        {
 070            if (assetBundlesLoadingCoroutine == null)
 071                return;
 72
 073            CoroutineStarter.Stop(assetBundlesLoadingCoroutine);
 074            highPriorityLoadQueue.Clear();
 075            lowPriorityLoadQueue.Clear();
 076        }
 77
 78        public void MarkAssetBundleForLoad(Asset_AB asset, AssetBundle assetBundle, Transform containerTransform, Action
 79        {
 1780            CheckForReprioritizeAwaitingAssets();
 81
 1782            AssetBundleInfo assetBundleToLoad = new AssetBundleInfo(asset, assetBundle, containerTransform, onSuccess, o
 83
 1784            float distanceFromPlayer = GetDistanceFromPlayer(containerTransform);
 1785            if (distanceFromPlayer <= MAX_SQR_DISTANCE_FOR_QUICK_LOADING)
 686                highPriorityLoadQueue.Enqueue(assetBundleToLoad);
 87            else
 1188                lowPriorityLoadQueue.Enqueue(assetBundleToLoad);
 1189        }
 90
 91        private IEnumerator LoadAssetBundlesCoroutine()
 92        {
 330293            while (true)
 94            {
 330995                while (highPriorityLoadQueue.Count > 0)
 96                {
 697                    float time = Time.realtimeSinceStartup;
 98
 699                    assetBundleInfoToLoad = highPriorityLoadQueue.Dequeue();
 6100                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 101
 6102                    if (IsLoadBudgetTimeReached(time))
 103                    {
 0104                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_NEARBY_ASSETS)
 0105                        time = Time.realtimeSinceStartup;
 106                    }
 107                }
 108
 3314109                while (lowPriorityLoadQueue.Count > 0 && highPriorityLoadQueue.Count == 0)
 110                {
 11111                    float time = Time.realtimeSinceStartup;
 112
 11113                    assetBundleInfoToLoad = lowPriorityLoadQueue.Dequeue();
 11114                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 115
 11116                    if (IsLoadBudgetTimeReached(time))
 117                    {
 4118                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_DISTANT_ASSETS
 4119                        time = Time.realtimeSinceStartup;
 120                    }
 121                }
 122
 3303123                yield return null;
 124            }
 125        }
 126
 127        private IEnumerator LoadAssetBundle(AssetBundleInfo assetBundleInfo)
 128        {
 17129            if (assetBundleInfo.assetBundle == null)
 130            {
 0131                assetBundleInfo.onFail?.Invoke();
 0132                yield break;
 133            }
 134
 17135            AssetBundleRequest abRequest = assetBundleInfo.assetBundle.LoadAllAssetsAsync();
 136
 73137            while (!abRequest.isDone)
 138            {
 56139                yield return null;
 140            }
 141
 17142            loadedAssetsByName = abRequest.allAssets.ToList();
 143
 140144            foreach (var loadedAsset in loadedAssetsByName)
 145            {
 53146                string ext = "any";
 147
 53148                if (loadedAsset is Texture textureAsset)
 149                {
 5150                    ext = "png";
 5151                }
 48152                else if (loadedAsset is Material)
 153                {
 11154                    ext = "mat";
 11155                }
 37156                else if (loadedAsset is Animation || loadedAsset is AnimationClip)
 157                {
 4158                    ext = "nim";
 4159                }
 33160                else if (loadedAsset is GameObject)
 161                {
 11162                    ext = "glb";
 163                }
 164
 53165                if (assetBundleInfo.asset?.assetsByExtension == null)
 166                {
 0167                    Debug.LogWarning($"Found an unexpected Null Reference: {assetBundleInfo.asset} or {assetBundleInfo.a
 0168                }
 169                else
 170                {
 53171                    if (!assetBundleInfo.asset.assetsByExtension.ContainsKey(ext))
 172                    {
 39173                        assetBundleInfo.asset.assetsByExtension.Add(ext, new List<UnityEngine.Object>());
 174                    }
 175
 53176                    assetBundleInfo.asset.assetsByExtension[ext].Add(loadedAsset);
 177                }
 178            }
 179
 17180            loadedAssetsByName.Clear();
 17181            assetBundleInfo.onSuccess?.Invoke();
 17182        }
 183
 184        private bool IsLoadBudgetTimeReached(float startTime)
 185        {
 17186            if (limitTimeBudget)
 187            {
 17188                currentLoadBudgetTime += Time.realtimeSinceStartup - startTime;
 17189                if (currentLoadBudgetTime > MAX_LOAD_BUDGET_TIME)
 190                {
 4191                    currentLoadBudgetTime = 0f;
 4192                    return true;
 193                }
 194            }
 195
 13196            return false;
 197        }
 198
 199        private IEnumerator WaitForSkippedFrames(int skippedFramesBetweenLoadings)
 200        {
 48201            for (int i = 0; i < skippedFramesBetweenLoadings; i++)
 202            {
 20203                yield return null;
 204            }
 4205        }
 206
 207        private void CheckForReprioritizeAwaitingAssets()
 208        {
 17209            if (lowPriorityLoadQueue.Count == 0 ||
 210                (Time.realtimeSinceStartup - lastQueuesReprioritizationTime) < TIME_BETWEEN_REPRIORITIZATIONS)
 17211                return;
 212
 0213            while (lowPriorityLoadQueue.Count > 0 && GetDistanceFromPlayer(lowPriorityLoadQueue.Peek().containerTransfor
 214            {
 0215                highPriorityLoadQueue.Enqueue(lowPriorityLoadQueue.Dequeue());
 0216                lastQueuesReprioritizationTime = Time.realtimeSinceStartup;
 217            }
 0218        }
 219
 220        private float GetDistanceFromPlayer(Transform containerTransform)
 221        {
 17222            return (containerTransform != null && limitTimeBudget) ? Vector3.SqrMagnitude(containerTransform.position - 
 223        }
 224    }
 225}