< 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:55
Uncovered lines:22
Coverable lines:77
Total lines:203
Line coverage:71.4% (55 of 77)
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%2.092071.43%
LoadAssetBundlesCoroutine()0%3012050%
LoadAssetBundle()0%13.113091.67%
IsLoadBudgetTimeReached(...)0%5.673033.33%
WaitForSkippedFrames()0%20400%
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 DCL.Helpers;
 6using DCL.Shaders;
 7using UnityEngine;
 8
 9namespace DCL
 10{
 11    public class AssetBundlesLoader
 12    {
 13        private const float MAX_LOAD_BUDGET_TIME = 0.05f;
 14        private const int SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_NEARBY_ASSETS = 1;
 15        private const int SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_DISTANT_ASSETS = 5;
 16        private const float MAX_SQR_DISTANCE_FOR_QUICK_LOADING = 6000f;
 17        private const float TIME_BETWEEN_REPRIORITIZATIONS = 1f;
 18
 19        private struct AssetBundleInfo
 20        {
 21            public Asset_AB asset;
 22            public Transform containerTransform;
 23            public Action onSuccess;
 24            public Action<Exception> onFail;
 25
 26            public AssetBundleInfo(Asset_AB asset, Transform containerTransform, Action onSuccess, Action<Exception> onF
 27            {
 2228                this.asset = asset;
 2229                this.containerTransform = containerTransform;
 2230                this.onSuccess = onSuccess;
 2231                this.onFail = onFail;
 2232            }
 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
 3858        private bool limitTimeBudget => CommonScriptableObjects.rendererState.Get();
 59
 60        public void Start()
 61        {
 4362            if (assetBundlesLoadingCoroutine != null)
 3763                return;
 64
 665            assetBundlesLoadingCoroutine = CoroutineStarter.Start(LoadAssetBundlesCoroutine());
 666        }
 67
 68        public void Stop()
 69        {
 3570            if (assetBundlesLoadingCoroutine == null)
 2971                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, Transform containerTransform, Action onSuccess, Action<Except
 81        {
 2282            CheckForReprioritizeAwaitingAssets();
 83
 2284            AssetBundleInfo assetBundleToLoad = new AssetBundleInfo(asset, containerTransform, onSuccess, onFail);
 85
 2286            float distanceFromPlayer = GetDistanceFromPlayer(containerTransform);
 87
 2288            if (distanceFromPlayer <= MAX_SQR_DISTANCE_FOR_QUICK_LOADING)
 2289                highPriorityLoadQueue.Enqueue(assetBundleToLoad);
 90            else
 091                lowPriorityLoadQueue.Enqueue(assetBundleToLoad);
 092        }
 93
 94        private IEnumerator LoadAssetBundlesCoroutine()
 95        {
 243896            while (true)
 97            {
 246698                while (highPriorityLoadQueue.Count > 0)
 99                {
 22100                    float time = Time.realtimeSinceStartup;
 101
 22102                    assetBundleInfoToLoad = highPriorityLoadQueue.Dequeue();
 22103                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 104
 22105                    if (IsLoadBudgetTimeReached(time))
 106                    {
 0107                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_NEARBY_ASSETS)
 0108                        time = Time.realtimeSinceStartup;
 109                    }
 110                }
 111
 2444112                while (lowPriorityLoadQueue.Count > 0 && highPriorityLoadQueue.Count == 0)
 113                {
 0114                    float time = Time.realtimeSinceStartup;
 115
 0116                    assetBundleInfoToLoad = lowPriorityLoadQueue.Dequeue();
 0117                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 118
 0119                    if (IsLoadBudgetTimeReached(time))
 120                    {
 0121                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_DISTANT_ASSETS
 0122                        time = Time.realtimeSinceStartup;
 123                    }
 124                }
 125
 2444126                yield return null;
 127            }
 128        }
 129
 130        private IEnumerator LoadAssetBundle(AssetBundleInfo assetBundleInfo)
 131        {
 22132            if (!assetBundleInfo.asset.IsValid())
 133            {
 0134                assetBundleInfo.onFail?.Invoke(new Exception("Asset bundle is null"));
 0135                yield break;
 136            }
 137
 22138            AssetBundleRequest abRequest = assetBundleInfo.asset.LoadAllAssetsAsync();
 139
 3192140            while (!abRequest.isDone) { yield return null; }
 141
 22142            loadedAssetsByName = abRequest.allAssets.ToList();
 143
 178144            foreach (var loadedAsset in loadedAssetsByName)
 145            {
 67146                string ext = "any";
 147
 74148                if (loadedAsset is Texture) { ext = "png"; }
 60149                else if (loadedAsset is Material material)
 150                {
 13151                    ShaderUtils.UpgradeMaterial_2020_To_2021(material);
 13152                    ext = "mat";
 153                }
 55154                else if (loadedAsset is Animation || loadedAsset is AnimationClip) { ext = "nim"; }
 52155                else if (loadedAsset is GameObject) { ext = "glb"; }
 156
 67157                assetBundleInfo.asset.AddAssetByExtension(ext, loadedAsset);
 158            }
 159
 22160            loadedAssetsByName.Clear();
 22161            assetBundleInfo.onSuccess?.Invoke();
 22162        }
 163
 164        private bool IsLoadBudgetTimeReached(float startTime)
 165        {
 22166            if (limitTimeBudget)
 167            {
 0168                currentLoadBudgetTime += Time.realtimeSinceStartup - startTime;
 169
 0170                if (currentLoadBudgetTime > MAX_LOAD_BUDGET_TIME)
 171                {
 0172                    currentLoadBudgetTime = 0f;
 0173                    return true;
 174                }
 175            }
 176
 22177            return false;
 178        }
 179
 180        private IEnumerator WaitForSkippedFrames(int skippedFramesBetweenLoadings)
 181        {
 0182            for (int i = 0; i < skippedFramesBetweenLoadings; i++) { yield return null; }
 0183        }
 184
 185        private void CheckForReprioritizeAwaitingAssets()
 186        {
 22187            if (lowPriorityLoadQueue.Count == 0 ||
 188                (Time.realtimeSinceStartup - lastQueuesReprioritizationTime) < TIME_BETWEEN_REPRIORITIZATIONS)
 22189                return;
 190
 0191            while (lowPriorityLoadQueue.Count > 0 && GetDistanceFromPlayer(lowPriorityLoadQueue.Peek().containerTransfor
 192            {
 0193                highPriorityLoadQueue.Enqueue(lowPriorityLoadQueue.Dequeue());
 0194                lastQueuesReprioritizationTime = Time.realtimeSinceStartup;
 195            }
 0196        }
 197
 198        private float GetDistanceFromPlayer(Transform containerTransform)
 199        {
 22200            return (containerTransform != null && limitTimeBudget) ? Vector3.SqrMagnitude(containerTransform.position - 
 201        }
 202    }
 203}