void InternalUnloadAllAssets(bool unloadUnusedAssets, Action completed)
        {
            Working = true;
            foreach (var kvp in m_LoadedAssets)
            {
                kvp.Value.Release(true);
                AssetRefer.Unspawn(kvp.Value);
            }
            foreach (var kvp in m_LoadedAssetBundles)
            {
                kvp.Value.Release(true);
                AssetBundleRefer.Unspawn(kvp.Value);
            }
            m_LoadedAssets.Clear();
            m_LoadedAssetBundles.Clear();

            if (unloadUnusedAssets)
            {
                Resources.UnloadUnusedAssets();
            }

            if (completed != null)
            {
                completed.Invoke();
            }

            Working = false;
            ActionSequence.Dequeue();
        }
 public static void Unspawn(AssetBundleRefer assetBundleRefer)
 {
     if (assetBundleRefer.Target != null)
     {
         assetBundleRefer.Count = 0;
         assetBundleRefer.Target.Unload(false);
         assetBundleRefer.Target = null;
     }
     Pool.Unspawn(assetBundleRefer);
 }
        public static AssetBundleRefer Spawn(AssetBundle assetBundle)
        {
            if (assetBundle == null)
            {
                throw new ArgumentException("assetBundle == null.");
            }
            AssetBundleRefer assetBundleRefer = Pool.Spawn();

            assetBundleRefer.Count  = 0;
            assetBundleRefer.Target = assetBundle;
            return(assetBundleRefer);
        }
        /// <summary>
        /// Stop all loading tasks, and release all references.(immediately)
        /// </summary>
        public AssetManagementTool Shutdown(bool unloadUnusedAssets = false)
        {
            ActionSequence.Clear();

            if (Working)
            {
                if (m_WorkingCoroutine != null)
                {
                    m_WorkingCoroutine.StopCoroutine();
                }
                Working = false;
            }
            m_WorkingCoroutine = null;

            if (m_LoadingTasks != null)
            {
                m_LoadingTasks.UnspawnLoadingTasks();
                m_LoadingTasks = null;
            }

            while (m_CachedLoadingTasks.Count > 0)
            {
                var list = m_CachedLoadingTasks.Dequeue();
                if (list != null)
                {
                    list.UnspawnLoadingTasks();
                }
            }
            m_CachedLoadingCallbacks.Clear();

            foreach (var kvp in m_LoadedAssets)
            {
                kvp.Value.Release(true);
                AssetRefer.Unspawn(kvp.Value);
            }
            foreach (var kvp in m_LoadedAssetBundles)
            {
                kvp.Value.Release(true);
                AssetBundleRefer.Unspawn(kvp.Value);
            }
            m_LoadedAssets.Clear();
            m_LoadedAssetBundles.Clear();

            if (unloadUnusedAssets)
            {
                Resources.UnloadUnusedAssets();
            }
            return(this);
        }
        public static void UnloadAssets(this List <string> assetPaths, Dictionary <string, AssetRefer> loadedAssets,
                                        Dictionary <string, AssetBundleRefer> loadedAssetBundles, AssetBundleManifest manifest, bool unloadUnusedAssets = false,
                                        Action completed = null)
        {
            var dirty = false;

            for (int i = 0, len = assetPaths.Count; i < len; i++)
            {
                var assetPath = assetPaths[i];

                AssetRefer assetRefer;
                if (loadedAssets.TryGetValue(assetPath, out assetRefer))
                {
                    if (assetRefer.Release() == 0)
                    {
                        // release assetBundle references.

                        loadedAssets.Remove(assetPath);
                        AssetRefer.Unspawn(assetRefer);
                        dirty = true;
                    }
                    else
                    {
                        // not need to release the assetBundle, because the reference count is bigger than zero.
                    }
                }

                var assetBundleNames = manifest.GetAllDependenciesByAssetPath(assetPath, true);

                for (int j = 0, len2 = assetBundleNames.Count; j < len2; j++)
                {
                    var assetBundleName = assetBundleNames[j];
                    AssetBundleRefer assetBundleRefer;
                    if (loadedAssetBundles.TryGetValue(assetBundleName, out assetBundleRefer))
                    {
                        if (assetBundleRefer.Release() == 0)
                        {
                            // release asset references.

                            loadedAssetBundles.Remove(assetBundleName);
                            AssetBundleRefer.Unspawn(assetBundleRefer);
                            dirty = true;
                        }
                        else
                        {
                            // not need to release the asset, because the reference count is bigger than zero.
                        }
                    }
                }
            }

            if (dirty && unloadUnusedAssets)
            {
                Resources.UnloadUnusedAssets();
            }

            if (completed != null)
            {
                completed.Invoke();
            }
        }
        public static IEnumerator LoadAssetsAsync <T>(this List <LoadingTask> loadingTasks, Dictionary <string, AssetRefer> loadedAssets,
                                                      Dictionary <string, AssetBundleRefer> loadedAssetBundles, Action <List <T> > completed, bool async = true) where T : Object
        {
            for (int i = 0, len = loadingTasks.Count; i < len; i++)
            {
                var task = loadingTasks[i];

                switch (task.TaskType)
                {
                case LoadingTaskType.LoadingSceneFromAssetBundle:
                case LoadingTaskType.LoadingScene: {
                    // load scene.

                    var scenceName = task.ScenceName;

                    if (async)
                    {
                        var asyncOperation = SceneManager.LoadSceneAsync(scenceName);

                        yield return(asyncOperation);

                        asyncOperation.allowSceneActivation = true;
                    }
                    else
                    {
                        SceneManager.LoadScene(scenceName);
                    }
                }
                break;

                case LoadingTaskType.LoadingAssetFromResources: {
                    var assetPath = task.AssetPath;

                    if (loadedAssets.ContainsKey(assetPath))
                    {
                        // asset is loaded, do nothing.
                    }
                    else
                    {
                        var resourcesPath = task.ResourcesPath;

                        Object asset;
                        if (async)
                        {
                            var request = Resources.LoadAsync <T>(resourcesPath);

                            while (!request.isDone)
                            {
                                yield return(null);
                            }

                            asset = request.asset;
                        }
                        else
                        {
                            asset = Resources.Load <T>(resourcesPath);
                        }

                        if (asset == null)
                        {
                            Debug.LogWarning("load asset from resources failed, resources path = " + resourcesPath);
                        }
                        else
                        {
                            // load asset from resources ok.

                            loadedAssets.Add(assetPath, AssetRefer.Spawn(asset));
                        }
                    }
                }
                break;

                case LoadingTaskType.LoadingAssetFromAssetBundle: {
                    var assetPath = task.AssetPath;

                    if (loadedAssets.ContainsKey(assetPath))
                    {
                        // asset is loaded, do nothing.
                    }
                    else
                    {
                        var assetBundleName = task.AssetBundleName;

                        AssetBundleRefer assetBundleRefer;
                        if (loadedAssetBundles.TryGetValue(assetBundleName, out assetBundleRefer))
                        {
                            Object asset;
                            if (async)
                            {
                                var request = assetBundleRefer.Target.LoadAssetAsync <T>(assetPath);

                                while (!request.isDone)
                                {
                                    yield return(null);
                                }

                                asset = request.asset;
                            }
                            else
                            {
                                asset = assetBundleRefer.Target.LoadAsset <T>(assetPath);
                            }

                            if (asset == null)
                            {
                                Debug.LogWarning("load asset from assetbundle failed, asset path = " + assetPath);
                            }
                            else
                            {
                                // load asset from assetbundle ok.

                                loadedAssets.Add(assetPath, AssetRefer.Spawn(asset));
                            }
                        }
                        else
                        {
                            Debug.LogWarning("not found loaded assetbundle, assetbundle name = " + assetBundleName);
                        }
                    }
                }
                break;

                case LoadingTaskType.LoadingAssetBundle: {
                    var assetBundleName = task.AssetBundleName;

                    if (loadedAssetBundles.ContainsKey(assetBundleName))
                    {
                        // assetbundle is loaded, do nothing.
                    }
                    else
                    {
                        // caculate assetbundle file path

                        var persistentDataPath = assetBundleName.GetAssetBundlePath();

                        if (File.Exists(persistentDataPath))
                        {
                            AssetBundle assetBundle;
                            if (async)
                            {
                                var request = AssetBundle.LoadFromFileAsync(persistentDataPath);
                                while (!request.isDone)
                                {
                                    yield return(null);
                                }

                                assetBundle = request.assetBundle;
                            }
                            else
                            {
                                assetBundle = AssetBundle.LoadFromFile(persistentDataPath);
                            }

                            if (assetBundle == null)
                            {
                                Debug.LogWarning("load assetbundle from file faile, file path = " + persistentDataPath);
                            }
                            else
                            {
                                // load assetbundle from file ok.
                                loadedAssetBundles.Add(assetBundleName, AssetBundleRefer.Spawn(assetBundle));
                            }
                        }
                        else
                        {
                            if (async)
                            {
                                var streamingAssetsPath = assetBundleName.GetAssetBundlePath(false);

#if UNITY_2018_4_OR_NEWER
                                UnityWebRequest unityWebRequest = UnityWebRequestAssetBundle.GetAssetBundle(streamingAssetsPath);
                                yield return(unityWebRequest.SendWebRequest());

                                var error = unityWebRequest.error;

                                if (string.IsNullOrEmpty(error))
                                {
                                    var download = unityWebRequest.downloadHandler as DownloadHandlerAssetBundle;
                                    if (download != null)
                                    {
                                        var assetBundle = download.assetBundle;

                                        if (assetBundle == null)
                                        {
                                            Debug.LogWarning("load assetbundle from streamingAssetPath failed, url = " + streamingAssetsPath);
                                        }
                                        else
                                        {
                                            loadedAssetBundles.Add(assetBundleName, AssetBundleRefer.Spawn(assetBundle));
                                        }
                                    }
                                    else
                                    {
                                        Debug.LogWarning("download assetbundle from streamingAssetPath failed, url = " + streamingAssetsPath);
                                    }
                                }
                                else
                                {
                                    Debug.LogWarning("load assetbundle failed, UnityWebRequest.error = " + error + ", url = " + streamingAssetsPath);
                                }
#else
                                using (var www = new WWW(streamingAssetsPath)) {
                                    while (!www.isDone)
                                    {
                                        yield return(null);
                                    }

                                    var error = www.error;

                                    if (string.IsNullOrEmpty(error))
                                    {
                                        var assetBundle = www.assetBundle;

                                        if (assetBundle == null)
                                        {
                                            Debug.LogWarning("load assetbundle from streamingAssetPath failed, url = " + streamingAssetsPath);
                                        }
                                        else
                                        {
                                            loadedAssetBundles.Add(assetBundleName, AssetBundleRefer.Spawn(assetBundle));
                                        }
                                    }
                                    else
                                    {
                                        Debug.LogWarning("load assetbundle failed, WWW.error = " + error + ", url = " + streamingAssetsPath);
                                    }
                                }
#endif
                            }
                            else
                            {
                                Debug.LogWarning("not found assetbundle file, file path = " + persistentDataPath);
                            }
                        }
                    }
                }
                break;
                } // end switch
            }     // end for

            List <T> result = new List <T>();

            for (int i = 0, len = loadingTasks.Count; i < len; i++)
            {
                var task = loadingTasks[i];

                switch (task.TaskType)
                {
                case LoadingTaskType.LoadingAssetFromResources:
                case LoadingTaskType.LoadingAssetFromAssetBundle: {
                    AssetRefer assetRefer;
                    if (loadedAssets.TryGetValue(task.AssetPath, out assetRefer))
                    {
                        assetRefer.Retain();
                        result.Add(assetRefer.GetAsset <T>());
                    }
                    else
                    {
                        result.Add(null);
                    }
                }
                break;

                case LoadingTaskType.LoadingScene:
                case LoadingTaskType.LoadingSceneFromAssetBundle: {
                    result.Add(null);
                }
                break;

                case LoadingTaskType.LoadingAssetBundle: {
                    AssetBundleRefer assetBundleRefer;
                    if (loadedAssetBundles.TryGetValue(task.AssetBundleName, out assetBundleRefer))
                    {
                        assetBundleRefer.Retain();
                    }
                    else
                    {
                        // loading assetbundle, but seems failed.
                    }
                }
                break;
                } // end switch
            }     // end for

            loadingTasks.UnspawnLoadingTasks();

            if (completed != null)
            {
                completed.Invoke(result);
            }
        }