< 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:82
Uncovered lines:8
Coverable lines:90
Total lines:224
Line coverage:91.1% (82 of 90)
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%220100%
MarkAssetBundleForLoad(...)0%220100%
LoadAssetBundlesCoroutine()0%12120100%
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<Exception> onFail;
 24
 25            public AssetBundleInfo(Asset_AB asset, AssetBundle assetBundle, Transform containerTransform, Action onSucce
 26            {
 2027                this.asset = asset;
 2028                this.assetBundle = assetBundle;
 2029                this.containerTransform = containerTransform;
 2030                this.onSuccess = onSuccess;
 2031                this.onFail = onFail;
 2032            }
 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
 3558        private bool limitTimeBudget => CommonScriptableObjects.rendererState.Get();
 59
 60        public void Start()
 61        {
 3962            if (assetBundlesLoadingCoroutine != null)
 3363                return;
 64
 665            assetBundlesLoadingCoroutine = CoroutineStarter.Start(LoadAssetBundlesCoroutine());
 666        }
 67
 68        public void Stop()
 69        {
 2070            if (assetBundlesLoadingCoroutine == null)
 1471                return;
 72
 673            CoroutineStarter.Stop(assetBundlesLoadingCoroutine);
 674            assetBundlesLoadingCoroutine = null;
 75
 676            highPriorityLoadQueue.Clear();
 677            lowPriorityLoadQueue.Clear();
 678        }
 79
 80        public void MarkAssetBundleForLoad(Asset_AB asset, AssetBundle assetBundle, Transform containerTransform, Action
 81        {
 2082            CheckForReprioritizeAwaitingAssets();
 83
 2084            AssetBundleInfo assetBundleToLoad = new AssetBundleInfo(asset, assetBundle, containerTransform, onSuccess, o
 85
 2086            float distanceFromPlayer = GetDistanceFromPlayer(containerTransform);
 2087            if (distanceFromPlayer <= MAX_SQR_DISTANCE_FOR_QUICK_LOADING)
 788                highPriorityLoadQueue.Enqueue(assetBundleToLoad);
 89            else
 1390                lowPriorityLoadQueue.Enqueue(assetBundleToLoad);
 1391        }
 92
 93        private IEnumerator LoadAssetBundlesCoroutine()
 94        {
 22195            while (true)
 96            {
 23497                while (highPriorityLoadQueue.Count > 0)
 98                {
 799                    float time = Time.realtimeSinceStartup;
 100
 7101                    assetBundleInfoToLoad = highPriorityLoadQueue.Dequeue();
 7102                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 103
 7104                    if (IsLoadBudgetTimeReached(time))
 105                    {
 1106                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_NEARBY_ASSETS)
 1107                        time = Time.realtimeSinceStartup;
 108                    }
 109                }
 110
 240111                while (lowPriorityLoadQueue.Count > 0 && highPriorityLoadQueue.Count == 0)
 112                {
 13113                    float time = Time.realtimeSinceStartup;
 114
 13115                    assetBundleInfoToLoad = lowPriorityLoadQueue.Dequeue();
 13116                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 117
 13118                    if (IsLoadBudgetTimeReached(time))
 119                    {
 4120                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_DISTANT_ASSETS
 4121                        time = Time.realtimeSinceStartup;
 122                    }
 123                }
 124
 227125                yield return null;
 126            }
 127        }
 128
 129        private IEnumerator LoadAssetBundle(AssetBundleInfo assetBundleInfo)
 130        {
 20131            if (assetBundleInfo.assetBundle == null)
 132            {
 0133                assetBundleInfo.onFail?.Invoke(new Exception("Asset bundle is null"));
 0134                yield break;
 135            }
 136
 20137            AssetBundleRequest abRequest = assetBundleInfo.assetBundle.LoadAllAssetsAsync();
 138
 88139            while (!abRequest.isDone)
 140            {
 68141                yield return null;
 142            }
 143
 20144            loadedAssetsByName = abRequest.allAssets.ToList();
 145
 158146            foreach (var loadedAsset in loadedAssetsByName)
 147            {
 59148                string ext = "any";
 149
 59150                if (loadedAsset is Texture textureAsset)
 151                {
 7152                    ext = "png";
 7153                }
 52154                else if (loadedAsset is Material)
 155                {
 12156                    ext = "mat";
 12157                }
 40158                else if (loadedAsset is Animation || loadedAsset is AnimationClip)
 159                {
 4160                    ext = "nim";
 4161                }
 36162                else if (loadedAsset is GameObject)
 163                {
 12164                    ext = "glb";
 165                }
 166
 59167                if (assetBundleInfo.asset?.assetsByExtension == null)
 168                {
 0169                    Debug.LogWarning($"Found an unexpected Null Reference: {assetBundleInfo.asset} or {assetBundleInfo.a
 0170                }
 171                else
 172                {
 59173                    if (!assetBundleInfo.asset.assetsByExtension.ContainsKey(ext))
 174                    {
 44175                        assetBundleInfo.asset.assetsByExtension.Add(ext, new List<UnityEngine.Object>());
 176                    }
 177
 59178                    assetBundleInfo.asset.assetsByExtension[ext].Add(loadedAsset);
 179                }
 180            }
 181
 20182            loadedAssetsByName.Clear();
 20183            assetBundleInfo.onSuccess?.Invoke();
 20184        }
 185
 186        private bool IsLoadBudgetTimeReached(float startTime)
 187        {
 20188            if (limitTimeBudget)
 189            {
 20190                currentLoadBudgetTime += Time.realtimeSinceStartup - startTime;
 20191                if (currentLoadBudgetTime > MAX_LOAD_BUDGET_TIME)
 192                {
 5193                    currentLoadBudgetTime = 0f;
 5194                    return true;
 195                }
 196            }
 197
 15198            return false;
 199        }
 200
 201        private IEnumerator WaitForSkippedFrames(int skippedFramesBetweenLoadings)
 202        {
 52203            for (int i = 0; i < skippedFramesBetweenLoadings; i++)
 204            {
 21205                yield return null;
 206            }
 5207        }
 208
 209        private void CheckForReprioritizeAwaitingAssets()
 210        {
 20211            if (lowPriorityLoadQueue.Count == 0 ||
 212                (Time.realtimeSinceStartup - lastQueuesReprioritizationTime) < TIME_BETWEEN_REPRIORITIZATIONS)
 20213                return;
 214
 0215            while (lowPriorityLoadQueue.Count > 0 && GetDistanceFromPlayer(lowPriorityLoadQueue.Peek().containerTransfor
 216            {
 0217                highPriorityLoadQueue.Enqueue(lowPriorityLoadQueue.Dequeue());
 0218                lastQueuesReprioritizationTime = Time.realtimeSinceStartup;
 219            }
 0220        }
 221
 20222        private float GetDistanceFromPlayer(Transform containerTransform) { return (containerTransform != null && limitT
 223    }
 224}