/// <summary>
        /// 同步加载资源
        /// </summary>
        /// <param name="ResObj">资源实例</param>
        private void LoadResource(ResObj resource)
        {
            //找配置
            ResPackInfo packInfo = GetResPackInfo(resource);

            if (packInfo != null)
            {
                if (packInfo.GetPackType() == (byte)ResPackType.ResPackTypeBundle)
                {
                    BundlePackInfo pi = packInfo as BundlePackInfo;
                    //跟随Resource
                    if (!pi.Outside && pi.IsNoBundle())
                    {
                        // load from Resources
                        resource.Load();
                    }
                    else
                    {
                        // load from bundle
                        // load bundle
                        BundleService.GetInstance().LoadSync(pi);
                        // load asset from bundle
                        AssetBundle bundle = BundleService.GetInstance().GetBundle(packInfo.Path);
                        if (bundle != null)
                        {
                            if (string.IsNullOrEmpty(resource.Ext))
                            {
                                resource.Ext = pi.GetResExt(resource.Path);
                            }
                            resource.Load(bundle);
                        }
                        else
                        {
                            JW.Common.Log.LogE("Loading bundle failed for path:{0}, bundle path:{1}", resource.Path, packInfo.Path);
                        }
                    }
                }
                else
                {
                    //二进制类型 直接根据文件路径 获取
                    resource.Load(packInfo.Path, packInfo.IsOutside(resource.Path));
                }
            }
            else
            {
                //不从属于任何资源包, 从Resources目录下读取 Editor模式 或者保护为未打包的
                resource.Load();
            }
        }
        /// <summary>
        /// 异步加载bundle列表
        /// </summary>
        /// <param name="packInfo">bundle打包信息</param>
        /// <param name="complete">加载完成回调</param>
        /// <param name="failure">加载失败回调</param>
        /// <param name="loading">加载进度回调</param>
        /// <returns></returns>
        public IEnumerator LoadAsync(JWObjList <BundlePackInfo> packInfos,
                                     BundleLoadedDelegate complete,
                                     BundleLoadFailedDelegate failure,
                                     BundleLoadingDelegate loading = null)
        {
            if (packInfos == null)
            {
                JW.Common.Log.LogE("Async loading bundle with null pack info.");
                yield break;
            }

            //JWObjList<BundleRef> bundleRefs = new JWObjList<BundleRef>();

            for (int i = 0; i < packInfos.Count; ++i)
            {
                BundlePackInfo packInfo = packInfos[i];
                if (packInfo != null)
                {
                    // ab has been loaded
                    BundleRef br = null;
                    if (_bundleDict.TryGetValue(packInfo.Path, out br))
                    {
                        br.RefCnt++;

                        if (_unloadingBundle.ContainsKey(packInfo.Path))
                        {
                            _unloadingBundle.Remove(packInfo.Path);
                        }

                        if (loading != null)
                        {
                            loading(packInfo, 1f);
                        }

                        if (complete != null)
                        {
                            complete(br);
                        }
                        continue;
                    }

                    // loading
                    if (_loadingBundle.Contains(packInfo.Path))
                    {
                        yield return(null);

                        while (_loadingBundle.Contains(packInfo.Path))
                        {
                            yield return(null);
                        }

                        if (_bundleDict.TryGetValue(packInfo.Path, out br))
                        {
                            br.RefCnt++;

                            if (complete != null)
                            {
                                complete(br);
                            }
                        }

                        continue;
                    }

                    if (packInfo.HasFlag(EBundleFlag.UnCompress) || packInfo.HasFlag(EBundleFlag.LZ4))
                    {
                        LoadSync(packInfo);
                        yield break;
                    }
                    //LZMA
                    // 放在加载依赖前,因为加载依赖表示已经开始加载了
                    _loadingBundle.Add(packInfo.Path);

                    // dependency
                    for (int j = 0; packInfo.Dependencies != null && j < packInfo.Dependencies.Count; j++)
                    {
                        yield return(StartCoroutine(LoadAsync(packInfo.Dependencies[j], null, null)));
                    }

                    // no bundle
                    if (packInfo.IsNoBundle() && !packInfo.Outside)
                    {
                        _loadingBundle.Remove(packInfo.Path);
                        yield break;
                    }

                    // load
                    string path = GetBundleFullPath(packInfo, true);
                    JW.Common.Log.LogD("Async load bundle liat path:{0}", path);
                    UnityWebRequest www = null;
                    www = UnityWebRequest.GetAssetBundle(path);
                    yield return(www.SendWebRequest());

                    // loading progress
                    if (loading != null)
                    {
                        float progress = 0.0f;
                        while (string.IsNullOrEmpty(www.error) && !www.isDone)
                        {
                            if (www.downloadProgress < 0.00001 && www.downloadProgress > -0.00001)
                            {
                                progress += 0.01f;
                                loading(packInfo, progress);
                            }
                            else
                            {
                                loading(packInfo, www.downloadProgress);
                            }

                            yield return(null);
                        }

                        if (string.IsNullOrEmpty(www.error))
                        {
                            loading(packInfo, 1f);
                        }
                    }

                    _loadingBundle.Remove(packInfo.Path);

                    // failed
                    if (!string.IsNullOrEmpty(www.error))
                    {
                        JW.Common.Log.LogE("Async loading bundle {0} failed, error:{1}", packInfo.Path, www.error);

                        if (failure != null)
                        {
                            failure(packInfo, www.error);
                        }

                        www.Dispose();

                        continue;
                    }

                    AssetBundle ab = DownloadHandlerAssetBundle.GetContent(www);
                    // succeed
                    if (ab != null)
                    {
                        br        = new BundleRef(packInfo);
                        br.Bundle = ab;
                        _bundleDict.Add(packInfo.Path, br);

                        if (complete != null)
                        {
                            complete(br);
                        }
                    }
                    www.Dispose();
                }
            }
        }
        /// <summary>
        /// 异步加载资源
        /// </summary>
        /// <param name="path">资源路径</param>
        /// <returns></returns>
        public ResObjRequest GetResourceAsync(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }
            // request
            ResObjRequest rr = new ResObjRequest();
            // complete loading
            Action <ResObj> complete = (ResObj r) =>
            {
                // try repaire
                //if (r.Content is GameObject)
                //{
                //    _repaireMachine.Repaire(r.Content as GameObject);
                //}
                rr.isDone   = true;
                rr.resource = r;
            };

            // loading progress
            Action <float> progress = (float prog) =>
            {
                rr.progress = prog;
            };

            // cache
            ResObj resource = _resCache.Add(path);

            if (resource.Content != null)
            {
                //cache包含直接返回
                complete(resource);
                return(rr);
            }

            // real loading
            ResPackInfo packInfo = GetResPackInfo(resource);

            if (packInfo != null)
            {
                //打包的资源AssetBundle
                if (packInfo.GetPackType() == (byte)ResPackType.ResPackTypeBundle)
                {
                    //AssetBundle 信息
                    BundlePackInfo pi = packInfo as BundlePackInfo;
                    //补充扩展名
                    if (string.IsNullOrEmpty(resource.Ext))
                    {
                        resource.Ext = pi.GetResExt(resource.Path);
                    }

                    // AssetBundle 缓存
                    AssetBundle bundle = BundleService.GetInstance().GetBundle(packInfo.Path);
                    if (bundle == null)
                    {
                        //不在外且跟随Resource出档了
                        if (!pi.Outside && pi.IsNoBundle())
                        {
                            // in Resources
                            StartCoroutine(resource.LoadAsync(complete, progress));
                        }
                        else
                        {
                            // load bundle first
                            StartCoroutine(BundleService.GetInstance().LoadAsync(pi, delegate(BundleRef bundleRef)
                            {
                                if (bundleRef != null && bundleRef.Bundle != null)
                                {
                                    bundle = bundleRef.Bundle;
                                    //从asset bundle 加载
                                    StartCoroutine(resource.LoadAsync(bundle, complete, progress));
                                }
                                else
                                {
                                    JW.Common.Log.LogE("Async loading bundle failed, resource:{0}, bundle:{1}", path, packInfo.Path);
                                    complete(null);
                                    _resCache.Remove(resource, true);
                                }
                            }, delegate(BundlePackInfo failedPackInfo, string error)
                            {
                                JW.Common.Log.LogE("Load bundle failed, error:{0}", error);
                                complete(null);
                                _resCache.Remove(resource, true);
                            }));
                        }
                    }
                    else
                    {
                        // bundle is exists
                        // 增加引用计数
                        BundleService.GetInstance().LoadSync(pi);
                        // 加载
                        StartCoroutine(resource.LoadAsync(bundle, complete, progress));
                    }
                }
                else
                {
                    //二进制文件包异步获取
                    StartCoroutine(resource.LoadAsync(packInfo.Path, packInfo.IsOutside(resource.Path), complete, progress));
                }
            }
            else
            {
                // 非IFS 打包资源,从Resources目录异步读取
                //JW.Common.Log.LogD("Load From Resource Async:"+ path);
                StartCoroutine(resource.LoadAsync(complete, progress));
            }
            return(rr);
        }
        //异步
        #region Load Asynchronize

        /// <summary>
        /// 异步加载bundle
        /// </summary>
        /// <param name="packInfo">bundle打包信息</param>
        /// <param name="complete">加载完成回调</param>
        /// <param name="failure">加载失败回调</param>
        /// <param name="loading">加载进度回调</param>
        /// <returns></returns>
        public IEnumerator LoadAsync(BundlePackInfo packInfo, BundleLoadedDelegate complete, BundleLoadFailedDelegate failure, BundleLoadingDelegate loading = null)
        {
            if (packInfo == null)
            {
                JW.Common.Log.LogE("Async loading bundle with null pack info.");
                yield break;
            }

            //判断是否已经加载
            BundleRef br = null;

            if (_bundleDict.TryGetValue(packInfo.Path, out br))
            {
                br.RefCnt++;

                if (_unloadingBundle.ContainsKey(packInfo.Path))
                {
                    _unloadingBundle.Remove(packInfo.Path);
                }

                if (loading != null)
                {
                    loading(packInfo, 1f);
                }

                if (complete != null)
                {
                    complete(br);
                }

                yield break;
            }

            // 正在加载
            if (_loadingBundle.Contains(packInfo.Path))
            {
                yield return(null);

                while (_loadingBundle.Contains(packInfo.Path))
                {
                    yield return(null);
                }

                if (_bundleDict.TryGetValue(packInfo.Path, out br))
                {
                    br.RefCnt++;

                    if (complete != null)
                    {
                        complete(br);
                    }
                }

                yield break;
            }
            //LoadFormFile 同步加载
            if (packInfo.HasFlag(EBundleFlag.UnCompress) || packInfo.HasFlag(EBundleFlag.LZ4))
            {
                LoadSync(packInfo);
                yield break;
            }

            //LZMA
            _loadingBundle.Add(packInfo.Path);
            // 依赖
            for (int i = 0; packInfo.Dependencies != null && i < packInfo.Dependencies.Count; i++)
            {
                yield return(StartCoroutine(LoadAsync(packInfo.Dependencies[i], null, null)));
            }
            // 内部含有
            if (packInfo.IsNoBundle() && !packInfo.Outside)
            {
                _loadingBundle.Remove(packInfo.Path);
                if (failure != null)
                {
                    failure(packInfo, "");
                }
                yield break;
            }

            {
                //对于LZMA AssetBundle.LoadFromFileAsync 会占用解压内存
                //手册说用UnityWebRequest 可以首次解压 后缓存,但对于本地的包又说用AssetBundle.LoadFromFileAsync
                string path = GetBundleFullPath(packInfo, false);
                JW.Common.Log.LogD("Async load bundle path:{0}", path);
                AssetBundleCreateRequest www = AssetBundle.LoadFromFileAsync(path);
                float progress = 0.0f;
                while (!www.isDone)
                {
                    if (loading != null)
                    {
                        if (www.progress < 0.00001 && www.progress > -0.00001)
                        {
                            progress += 0.01f;
                            loading(packInfo, progress);
                        }
                        else
                        {
                            loading(packInfo, www.progress);
                        }
                    }
                    yield return(null);
                }

                _loadingBundle.Remove(packInfo.Path);
                // failed
                if (www.assetBundle == null)
                {
                    JW.Common.Log.LogE("Async loading bundle {0} failed, error:{1}", path, "");
                    if (failure != null)
                    {
                        failure(packInfo, "");
                    }
                    www = null;
                    yield break;
                }

                if (loading != null)
                {
                    loading(packInfo, 1f);
                }

                // succeed
                if (www.assetBundle != null)
                {
                    br        = new BundleRef(packInfo);
                    br.Bundle = www.assetBundle;
                    _bundleDict.Add(packInfo.Path, br);

                    if (complete != null)
                    {
                        complete(br);
                    }
                }
                www = null;
            }

            /*Test2
             * {
             *  string path = GetBundleFullPath(packInfo, true);
             *  JW.Common.Log.LogD("Async load bundle use UnityWebRequest path:{0}", path);
             *  UnityWebRequest www = UnityWebRequest.GetAssetBundle(path);
             *  yield return www.SendWebRequest();
             *  float progress = 0.0f;
             *  while (!www.isDone)
             *  {
             *      if (loading != null)
             *      {
             *          if (www.downloadProgress < 0.00001 && www.downloadProgress > -0.00001)
             *          {
             *              progress += 0.01f;
             *              loading(packInfo, progress);
             *          }
             *          else
             *          {
             *              loading(packInfo, www.downloadProgress);
             *          }
             *      }
             *      yield return null;
             *  }
             *
             *  _loadingBundle.Remove(packInfo.Path);
             *  // failed
             *  AssetBundle ab = DownloadHandlerAssetBundle.GetContent(www);
             *  if (ab == null)
             *  {
             *      JW.Common.Log.LogE("Async loading bundle use UnityWebRequest {0} failed, error:{1}", path, "");
             *      if (failure != null)
             *      {
             *          failure(packInfo, "");
             *      }
             *      www.Dispose();
             *      www = null;
             *      yield break;
             *  }
             *
             *  if (loading != null)
             *  {
             *      loading(packInfo, 1f);
             *  }
             *
             *  // succeed
             *  if (ab != null)
             *  {
             *      br = new BundleRef(packInfo);
             *      br.Bundle = ab;
             *      _bundleDict.Add(packInfo.Path, br);
             *
             *      if (complete != null)
             *      {
             *          complete(br);
             *      }
             *  }
             *  www.Dispose();
             *  www = null;
             * }*/
        }