private const int MaxTryNum     = 3;  // 最多重试次数

        private void Update( )
        {
            // 下载量充足,增加新的下载
            if (_loadingQueue.Count < MaxWorkingCnt)
            {
                int cnt = MaxWorkingCnt - _waitingQueue.Count;

                for (int i = 0; i < cnt; i++)
                {
                    if (_waitingQueue.Count <= 0)
                    {
                        break;
                    }

                    string url = _waitingQueue.Dequeue( );
                    _loadingQueue.Add(new LoadingAbInfo(url));
                }
            }

            // 检查下载状态
            for (var index = _loadingQueue.Count - 1; index >= 0; index--)
            {
                LoadingAbInfo info = _loadingQueue[index];
                if (info.State == LoadStateType.Loding)
                {
                    continue;
                }

                // 三次都没有下载下来
                if (info.ErrorCount >= MaxTryNum)
                {
                    GameLogger.GetInstance( )
                    .Output(string.Format("!!!!! AssetBundle CreateFromWWW failed: {0}\n\t ErrorCount >= {1}",
                                          info.Url, MaxTryNum));
                    _loadingQueue.RemoveAt(index);
                    continue;
                }

                StartCoroutine(OnAssetLoadStart(info));
            }

            // 检查request的完成情况
            List <string> tmpKeys = new List <string>(_requests.Keys);

            foreach (var one in tmpKeys)
            {
                AsyncLoadRequest request = _requests[one];
                if (request.CompletedCallback( ))
                {
                    _requests.Remove(one);
                }
            }
        }
        private IEnumerator OnAssetLoadStart(LoadingAbInfo info)
        {
#if TRACE
            //float timeBegin = Time.realtimeSinceStartup;
            //GameLogger.GetInstance().Trace( "AssetBundle CreateFromWWW Star: {0}", info.Url );
#endif

            info.State = LoadStateType.Loding;
            yield return(null);

            var url = MakeUrl(info.Url);
            WWW www = new WWW(url);
            while (!www.isDone)
            {
                info.Progress = www.progress;
                yield return(null);
            }

            // 加载失败了
            if (!string.IsNullOrEmpty(www.error))
            {
                GameLogger.GetInstance( ).Trace("AssetBundle CreateFromWWW failed: {0}\n\t{1}", url, www.error);
                UrlLoadCompleted(info, null);
                yield break;
            }

            AssetBundle ab = www.assetBundle;
            if (ab == null)
            {
                GameLogger.GetInstance( ).Trace("AssetBundle CreateFromWWW failed: {0}\n\tab == null", url);
                UrlLoadCompleted(info, null);
                yield break;
            }

#if TRACE
            //GameLogger.GetInstance().Trace( "### Load {0} successful, time = {1}", info.Url, Time.realtimeSinceStartup - timeBegin );
#endif

            UrlLoadCompleted(info, ab);
        }
        private void UrlLoadCompleted(LoadingAbInfo info, AssetBundle ab)
        {
            if (ab == null)
            {
                if (info.ErrorCount >= MaxTryNum)
                {
                }
                else
                {
                    // 再试几次下载
                    info.State       = LoadStateType.Start;
                    info.ErrorCount += 1;
                }
                //GameLogger.GetInstance( ).Debug( "!!!!! Failed..UrlLoadCompleted:" + info.Url );
                return;
            }

            GameLogger.GetInstance( ).Debug("UrlLoadCompleted:" + info.Url);

            // 缓存起来
            _cacheMgr.Add(info.Url, ab);

            // 修改下载数据状态
            info.State = LoadStateType.Completed;

            // 通知Request,有一个AB下载完成
            if (!_loadedCallback.ContainsKey(info.Url))
            {
                throw new Exception($"!!!UrlLoadCompleted failed. Url:{info.Url}");
            }

            // 回调
            _loadedCallback[info.Url].DynamicInvoke(info.Url, ab);
            _loadedCallback.Remove(info.Url);

            // 加载完成
            _loadingQueue.Remove(info);
        }