/// <summary>
    /// 映射asset和asset bundle之间的路径关系
    /// 1. 先映射只读文件夹里的
    /// 2. 再映射读写文件夹里的
    /// 因为只读文件需要使用www读取,所以理论上是异步读取,要通过回调函数返回完成
    /// </summary>
    /// <param name="_complete"></param>
    private void MappingAssetToAssetBundle(Action _complete)
    {
        // 先映射StreamingAssets下的
        var readOnlyVersionFileDir = AssetBundleDefine.GetReadOnlyPathByWWW();

        WWWLoadBytes.Instance.LoadBytes(
            string.Format("{0}/{1}", readOnlyVersionFileDir, AssetBundleDefine.VERSION_LOCAL_FILE),
            (s, bytes, _errorMessage) =>
        {
            if (false == string.IsNullOrEmpty(_errorMessage))
            {
                this.Error("无法读取StreamingAsset中的文件配置 url : " + s + " error message : " + _errorMessage);
            }

            MappingAssetToAssetBundle(GameFramework.Utility.Zip.Decompress(bytes),
                                      string.Format("{0}/{1}/{2}", UnityEngine.Application.streamingAssetsPath,
                                                    AssetBundleDefine.READ_ONLY_DIR, AssetBundleDefine.RuntimePlatformName()));

            // 再映射可读写目录的
            var versionFileBytes = FileSystemFacade.Instance.ReadFile(AssetBundleDefine.GetReadWritePath());

            MappingAssetToAssetBundle(versionFileBytes /**已经是解压过的*/,
                                      string.Format("{0}/{1}/{2}", UnityEngine.Application.persistentDataPath,
                                                    AssetBundleDefine.AssetBundlesDir, AssetBundleDefine.RuntimePlatformName()));

            if (null != _complete)
            {
                _complete();
            }
        });
    }
    /// <summary>
    /// 获取一个资源的下载路径
    /// </summary>
    /// <param name="_versionItem"></param>
    /// <returns></returns>
    private string GetDownloadPath(AssetBundleVersionItem _versionItem)
    {
        if (null == _versionItem)
        {
            return(null);
        }
        string downloadFullPath =
            string.Format("{0}/{1}/{2}${3}.dat", AssetBundleDefine.SERVER_RES_PATH, AssetBundleDefine.RuntimePlatformName(), _versionItem.ItemName, _versionItem.MD5);

        return(downloadFullPath);
    }
    /// <summary>
    /// 游戏开始下载必要数据
    /// </summary>
    private void GameStartDownload()
    {
        startDownloadHandler = GetDownloadHandler(AssetPathType.persisent);
        if (null != startDownloadHandler)
        {
            // 添加Manifest的下载
            startDownloadHandler.AddTask(
                string.Format("{0}/{1}/{2}", AssetBundleDefine.SERVER_RES_PATH, AssetBundleDefine.RuntimePlatformName(), AssetBundleDefine.MANIFEST_FILE),
                DownloadResType.ByteArray, ManifestDlwonloadComplete, null);

            startDownloadHandler.SetCallBack(DownloadUpdateInfo, GameStartDownloadComplete);
            startDownloadHandler.StartDownload();
        }
    }
    /// <summary>
    /// asset bundle 依赖关系映射
    /// </summary>
    private void AssetBundleDependent()
    {
        // 读取manifest文件
        string manifestFilePath = string.Format("{0}/{1}/{2}/{3}", App.Make <IFileDiskSystem>().GetDiskPath(),
                                                AssetBundleDefine.AssetBundlesDir, AssetBundleDefine.RuntimePlatformName(), AssetBundleDefine.MANIFEST_FILE);
        var manifestAssetBundle = AssetBundle.LoadFromFile(manifestFilePath);

        if (null != manifestAssetBundle)
        {
            var manifest = manifestAssetBundle.LoadAsset <AssetBundleManifest>("AssetBundleManifest");
            if (null != manifest)
            {
                dependentAssetBundles.Clear();                         // 先清空列表
                string[] assetBundles = manifest.GetAllAssetBundles(); // 只有存在依赖关系的,才会再这个数组中,Scene不会
                if (null == assetBundles || assetBundles.Length <= 0)
                {
                    return;
                }

                foreach (string bundle in assetBundles)
                {
                    if (null == bundle)
                    {
                        continue;
                    }

                    string[] dependencies = manifest.GetAllDependencies(bundle);

                    if (true == dependentAssetBundles.ContainsKey(bundle))
                    {
                        dependentAssetBundles.Remove(bundle);
                    }

                    if (dependencies.Length > 0)
                    {
                        dependentAssetBundles.Add(bundle, dependencies); // 如果依赖关系 大于0 ,则添加到依赖关系队列中
                    }
                }
            }

            manifestAssetBundle.Unload(true);
        }
    }
    /// <summary>
    /// 资源更新入口
    /// </summary>
    public void UpdateGameResources()
    {
        string versionFile = string.Format("{0}/{1}/{2}", AssetBundleDefine.SERVER_RES_PATH, AssetBundleDefine.RuntimePlatformName(), AssetBundleDefine.VERSION_FILE);

        this.Info("version file path = " + versionFile);
        App.Make <IHttpRequest>().GetBytes(versionFile, bytes =>
        {
            if (null == bytes || bytes.Length <= 0)
            {
                this.Error("Version文件下载失败");
                return;
            }

            var decompressBytes   = GameFramework.Utility.Zip.Decompress(bytes);
            string versionContent = System.Text.Encoding.UTF8.GetString(decompressBytes);
            if (true == string.IsNullOrEmpty(versionContent))
            {
                this.Error("Version文件解析失败");
                return;
            }

            // 存入本地,并不是做对比使用,而是name和path映射做准备
            App.Make <IFileDiskSystem>()
            .CreateFile(string.Format("{0}/{1}/{2}", AssetBundleDefine.AssetBundlesDir, AssetBundleDefine.RuntimePlatformName(), AssetBundleDefine.VERSION_FILE),
                        decompressBytes);

            serverVersion = JsonUtility.FromJson <AssetBundleVersion>(versionContent);
            if (null == serverVersion)
            {
                this.Error("version文件转换失败");
                return;
            }

            var downloadList = CheckDownloadList(serverVersion.AssetBundleVersionItems, AssetPathType.persisent);
            downloadInfo.SetDownloadList(AssetPathType.persisent, downloadList);

            if (downloadList.Count > 0)
            {
                this.Debug("总计下载文件个数 = " + downloadList.Count + "  大小 = " + downloadInfo.DownloadSizeCountDes);
                // 这里要根据网络情况,判断是否直接下载

                if (UnityEngine.Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork)                 // 移动网络
                {
                    // 开始下载
                    AppEvent.BroadCastEvent(AssetBundleDefine.EVENT_GAME_START_RESOURCES_UPDATE);
                }
                else if (UnityEngine.Application.internetReachability == NetworkReachability.ReachableViaCarrierDataNetwork)                  // WIFI网络
                {
                    // 询问玩家
                    AppEvent.BroadCastEvent(AssetBundleDefine.EVENT_ASK_UPDATE_RESOURCES, downloadInfo);
                }
            }
            else
            {
                GameStartDownloadComplete(null);                 // 没有最新资源需要下载
            }
        }, _errorCode =>
        {
            this.Error("Version文件下载失败 error code = " + _errorCode);
        });
    }
    /// <summary>
    /// 获取本地存储路径
    /// </summary>
    /// <param name="_versionItem"></param>
    /// <returns></returns>
    public static string GetFileLocalPath(AssetBundleVersionItem _versionItem)
    {
        if (null == _versionItem)
        {
            return(null);
        }

        string fileFullPath = string.Format("{0}/{1}/{2}${3}.dat", AssetBundleDefine.AssetBundlesDir, AssetBundleDefine.RuntimePlatformName(), _versionItem.ItemName, _versionItem.MD5);

        return(fileFullPath);
    }
    /// <summary>
    /// 将manifest写入本地
    /// </summary>
    /// <param name="s"></param>
    /// <param name="o"></param>
    /// <param name="arg3"></param>
    private void ManifestDlwonloadComplete(string s, object o, object arg3)
    {
        byte[] bytes     = (byte[])o;
        string localPath = string.Format("{0}/{1}/{2}", AssetBundleDefine.AssetBundlesDir, AssetBundleDefine.RuntimePlatformName(), AssetBundleDefine.MANIFEST_FILE);

        App.Make <IFileDiskSystem>().CreateFile(localPath, bytes);
    }