< 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:75
Uncovered lines:14
Coverable lines:89
Total lines:225
Line coverage:84.2% (75 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%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 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
 3458        private bool limitTimeBudget => CommonScriptableObjects.rendererState.Get();
 59
 60        public void Start()
 61        {
 3962            if (assetBundlesLoadingCoroutine != null)
 3863                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        {
 2080            CheckForReprioritizeAwaitingAssets();
 81
 2082            AssetBundleInfo assetBundleToLoad = new AssetBundleInfo(asset, assetBundle, containerTransform, onSuccess, o
 83
 2084            float distanceFromPlayer = GetDistanceFromPlayer(containerTransform);
 2085            if (distanceFromPlayer <= MAX_SQR_DISTANCE_FOR_QUICK_LOADING)
 886                highPriorityLoadQueue.Enqueue(assetBundleToLoad);
 87            else
 1288                lowPriorityLoadQueue.Enqueue(assetBundleToLoad);
 1289        }
 90
 91        private IEnumerator LoadAssetBundlesCoroutine()
 92        {
 287593            while (true)
 94            {
 288495                while (highPriorityLoadQueue.Count > 0)
 96                {
 897                    float time = Time.realtimeSinceStartup;
 98
 899                    assetBundleInfoToLoad = highPriorityLoadQueue.Dequeue();
 8100                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 101
 8102                    if (IsLoadBudgetTimeReached(time))
 103                    {
 1104                        yield return WaitForSkippedFrames(SKIPPED_FRAMES_AFTER_BUDGET_TIME_IS_REACHED_FOR_NEARBY_ASSETS)
 1105                        time = Time.realtimeSinceStartup;
 106                    }
 107                }
 108
 2888109                while (lowPriorityLoadQueue.Count > 0 && highPriorityLoadQueue.Count == 0)
 110                {
 12111                    float time = Time.realtimeSinceStartup;
 112
 12113                    assetBundleInfoToLoad = lowPriorityLoadQueue.Dequeue();
 12114                    yield return LoadAssetBundle(assetBundleInfoToLoad);
 115
 12116                    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
 2876123                yield return null;
 124            }
 125        }
 126
 127        private IEnumerator LoadAssetBundle(AssetBundleInfo assetBundleInfo)
 128        {
 20129            if (assetBundleInfo.assetBundle == null)
 130            {
 0131                assetBundleInfo.onFail?.Invoke();
 0132                yield break;
 133            }
 134
 20135            AssetBundleRequest abRequest = assetBundleInfo.assetBundle.LoadAllAssetsAsync();
 136
 77137            while (!abRequest.isDone)
 138            {
 57139                yield return null;
 140            }
 141
 20142            loadedAssetsByName = abRequest.allAssets.ToList();
 143
 158144            foreach (var loadedAsset in loadedAssetsByName)
 145            {
 59146                string ext = "any";
 147
 59148                if (loadedAsset is Texture)
 149                {
 7150                    ext = "png";
 7151                }
 52152                else if (loadedAsset is Material)
 153                {
 12154                    ext = "mat";
 12155                }
 40156                else if (loadedAsset is Animation || loadedAsset is AnimationClip)
 157                {
 4158                    ext = "nim";
 4159                }
 36160                else if (loadedAsset is GameObject)
 161                {
 12162                    ext = "glb";
 163                }
 164
 59165                if (assetBundleInfo.asset?.assetsByExtension == null)
 166                {
 0167                    Debug.LogWarning($"Found an unexpected Null Reference: {assetBundleInfo.asset} or {assetBundleInfo.a
 0168                }
 169                else
 170                {
 59171                    if (!assetBundleInfo.asset.assetsByExtension.ContainsKey(ext))
 172                    {
 44173                        assetBundleInfo.asset.assetsByExtension.Add(ext, new List<UnityEngine.Object>());
 174                    }
 175
 59176                    assetBundleInfo.asset.assetsByExtension[ext].Add(loadedAsset);
 177                }
 178            }
 179
 20180            loadedAssetsByName.Clear();
 20181            assetBundleInfo.onSuccess?.Invoke();
 20182        }
 183
 184        private bool IsLoadBudgetTimeReached(float startTime)
 185        {
 20186            if (limitTimeBudget)
 187            {
 20188                currentLoadBudgetTime += Time.realtimeSinceStartup - startTime;
 20189                if (currentLoadBudgetTime > MAX_LOAD_BUDGET_TIME)
 190                {
 5191                    currentLoadBudgetTime = 0f;
 5192                    return true;
 193                }
 194            }
 195
 15196            return false;
 197        }
 198
 199        private IEnumerator WaitForSkippedFrames(int skippedFramesBetweenLoadings)
 200        {
 52201            for (int i = 0; i < skippedFramesBetweenLoadings; i++)
 202            {
 21203                yield return null;
 204            }
 5205        }
 206
 207        private void CheckForReprioritizeAwaitingAssets()
 208        {
 20209            if (lowPriorityLoadQueue.Count == 0 ||
 210                (Time.realtimeSinceStartup - lastQueuesReprioritizationTime) < TIME_BETWEEN_REPRIORITIZATIONS)
 20211                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        {
 20222            return (containerTransform != null && limitTimeBudget) ? Vector3.SqrMagnitude(containerTransform.position - 
 223        }
 224    }
 225}