/// <summary> /// 获取资源包信息(这个方法一定要能返回资源信息) /// </summary> /// <param name="assetbundlePath"></param> /// <returns></returns> public AssetBundleInfoEntity GetAssetBundleInfo(string assetbundlePath) { AssetBundleInfoEntity entity = null; m_CNDVersionDic.TryGetValue(assetbundlePath, out entity); return(entity); }
/// <summary> /// 将只读区版本文件初始化到可写区 /// </summary> private void InitVersionFileFormStreamingAssetsToLocal() { GameEntry.Log(LogCategory.Resource, "InitVersionFileFormStreamingAssetsToLocal"); m_LocalAssetsVersionDic = new Dictionary <string, AssetBundleInfoEntity>(); var enumerator = m_StreamingAssetsVersionDic.GetEnumerator(); while (enumerator.MoveNext()) { AssetBundleInfoEntity entity = enumerator.Current.Value; m_LocalAssetsVersionDic[enumerator.Current.Key] = new AssetBundleInfoEntity() { AssetBundleName = entity.AssetBundleName, MD5 = entity.MD5, Size = entity.Size, IsFirstData = entity.IsFirstData, IsEncrypt = entity.IsEncrypt }; } //保存版本文件 LocalAssetsManager.SaveVersionFile(m_LocalAssetsVersionDic); //保存版本号 m_LocalAssetsVersion = m_StreamingAssetsVersion; LocalAssetsManager.SetResourceVersion(m_LocalAssetsVersion); }
/// <summary> /// 根据字节数组获取资源包版本信息 /// </summary> /// <param name="buffer">字节数组</param> /// <param name="version">版本号</param> /// <returns></returns> public static Dictionary <string, AssetBundleInfoEntity> GetAssetBundleVersionList(byte[] buffer, ref string version) { buffer = ZlibHelper.DeCompressBytes(buffer); Dictionary <string, AssetBundleInfoEntity> dic = new Dictionary <string, AssetBundleInfoEntity>(); MMO_MemoryStream ms = new MMO_MemoryStream(buffer); int len = ms.ReadInt(); for (int i = 0; i < len; i++) { if (i == 0) { version = ms.ReadUTF8String().Trim(); } else { AssetBundleInfoEntity entity = new AssetBundleInfoEntity(); entity.AssetBundleName = ms.ReadUTF8String(); entity.MD5 = ms.ReadUTF8String(); entity.Size = ms.ReadULong(); entity.IsFirstData = ms.ReadByte() == 1; entity.IsEncrypt = ms.ReadByte() == 1; dic[entity.AssetBundleName] = entity; } } return(dic); }
/// <summary> /// 保存版本信息 /// </summary> /// <param name="entity"></param> public void SaveVersion(AssetBundleInfoEntity entity) { if (m_LocalAssetsVersionDic == null) { m_LocalAssetsVersionDic = new Dictionary <string, AssetBundleInfoEntity>(); } m_LocalAssetsVersionDic[entity.AssetBundleName] = entity; //保存版本文件 LocalAssetsManager.SaveVersionFile(m_LocalAssetsVersionDic); }
/// <summary> /// 开始下载 /// </summary> /// <param name="url"></param> public void BeginDownload(string url, AssetBundleInfoEntity assetBundleInfo, BaseAction <string, ulong, float> onUpdate = null, BaseAction <string, DownloadRoutine> onComplete = null) { m_CurrFileUrl = url; m_CurrAssetBundleInfo = assetBundleInfo; m_OnUpdate = onUpdate; m_OnComplete = onComplete; m_DownloadLocalFilePath = string.Format("{0}/{1}", GameEntry.Resource.LocalFilePath, m_CurrFileUrl); //判断如果本地已经有目标文件 先删除 if (File.Exists(m_DownloadLocalFilePath)) { File.Delete(m_DownloadLocalFilePath); } m_DownloadLocalFilePath = m_DownloadLocalFilePath + ".temp"; if (File.Exists(m_DownloadLocalFilePath)) { //Debug.LogError("验证MD5 如果以前残留文件的MD5和CDN的不一致 则删除本地临时文件 重新下载"); if (PlayerPrefs.HasKey(m_CurrFileUrl)) { //验证 if (!PlayerPrefs.GetString(m_CurrFileUrl).Equals(assetBundleInfo.MD5, System.StringComparison.CurrentCultureIgnoreCase)) { //Debug.LogError("如果不一致 则删除本地临时文件 重新下载"); File.Delete(m_DownloadLocalFilePath); BeginDownload(); } else { //Debug.LogError("一致 继续下载"); m_FileStream = File.OpenWrite(m_DownloadLocalFilePath); m_FileStream.Seek(0, SeekOrigin.End); m_BeginPos = (uint)m_FileStream.Length; Download(string.Format("{0}{1}", GameEntry.Data.SysDataManager.CurrChannelConfig.RealSourceUrl, m_CurrFileUrl), m_BeginPos); } } else { //Debug.LogError("本地没有MD5记录 重新下载"); File.Delete(m_DownloadLocalFilePath); BeginDownload(); } } else { BeginDownload(); } }
/// <summary> /// 下载多个文件 /// </summary> /// <param name="lstUrl"></param> /// <param name="onDownloadMulitUpdate"></param> /// <param name="onDownloadMulitComplete"></param> public void BeginDownloadMulit(LinkedList <string> lstUrl, BaseAction <int, int, ulong, ulong> onDownloadMulitUpdate = null, BaseAction onDownloadMulitComplete = null) { m_OnDownloadMulitUpdate = onDownloadMulitUpdate; m_OnDownloadMulitComplete = onDownloadMulitComplete; m_NeedDownloadList.Clear(); m_DownloadMulitCurrSizeDic.Clear(); m_DownloadMulitNeedCount = 0; m_DownloadMulitCurrCount = 0; m_DownloadMulitTotalSize = 0; m_DownloadMulitCurrSize = 0; //1.把需要下载的加入下载队列 for (LinkedListNode <string> item = lstUrl.First; item != null; item = item.Next) { string url = item.Value; AssetBundleInfoEntity entity = GameEntry.Resource.ResourceManager.GetAssetBundleInfo(url); if (entity != null) { m_DownloadMulitTotalSize += entity.Size; m_DownloadMulitNeedCount++; m_NeedDownloadList.AddLast(url); m_DownloadMulitCurrSizeDic[url] = 0; } else { GameEntry.LogError("无效资源包=>" + url); } } //下载器数量 最多5个 int routineCount = Mathf.Min(GameEntry.Download.DownloadRoutineCount, m_NeedDownloadList.Count); for (int i = 0; i < routineCount; i++) { DownloadRoutine routine = GameEntry.Pool.DequeueClassObject <DownloadRoutine>(); string url = m_NeedDownloadList.First.Value; m_NeedDownloadList.RemoveFirst(); AssetBundleInfoEntity entity = GameEntry.Resource.ResourceManager.GetAssetBundleInfo(url); routine.BeginDownload(url, entity, OnDownloadMulitUpdate, OnDownloadMulitComplete); m_DownloadRoutineList.AddLast(routine); } }
/// <summary> /// 加载资源包 /// </summary> /// <param name="assetbundlePath"></param> public void LoadAssetBundle(string assetbundlePath) { m_CurrAssetBundleInfo = GameEntry.Resource.ResourceManager.GetAssetBundleInfo(assetbundlePath); //检查文件在可写区是否存在 bool isExistsInLocal = GameEntry.Resource.ResourceManager.LocalAssetsManager.CheckFileExists(assetbundlePath); if (isExistsInLocal && !m_CurrAssetBundleInfo.IsEncrypt) { //如果资源包存在于可写区 并且没有加密 m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(string.Format("{0}/{1}", Application.persistentDataPath, assetbundlePath)); } else { byte[] buffer = GameEntry.Resource.ResourceManager.LocalAssetsManager.GetFileBuffer(assetbundlePath); if (buffer == null) { //如果可写区没有 那么就从只读区获取 GameEntry.Resource.ResourceManager.StreamingAssetsManager.ReadAssetBundle(assetbundlePath, (byte[] buff) => { if (buff == null) { Debug.LogError("资源包需要下载assetbundlePath=>" + assetbundlePath); GameEntry.Download.BeginDownloadSingle(assetbundlePath, onComplete: (string fileUrl) => { Debug.LogError("下载完毕fileUrl=>" + fileUrl); buffer = GameEntry.Resource.ResourceManager.LocalAssetsManager.GetFileBuffer(fileUrl); Debug.LogError("准备加载资源包=" + buffer); LoadAssetBundleAsync(buffer); }); } else { LoadAssetBundleAsync(buff); } }); } else { LoadAssetBundleAsync(buffer); } } }
/// <summary> /// 多文件下载完毕回调 /// </summary> /// <param name="fileUrl"></param> /// <param name="routine"></param> private void OnDownloadMulitComplete(string fileUrl, DownloadRoutine routine) { //检查队列中是否有要下载的数据 if (m_NeedDownloadList.Count > 0) { //让下载器继续工作 string url = m_NeedDownloadList.First.Value; m_NeedDownloadList.RemoveFirst(); //Debug.LogError("让下载器继续工作 下载="+ url); AssetBundleInfoEntity entity = GameEntry.Resource.ResourceManager.GetAssetBundleInfo(url); routine.BeginDownload(url, entity, OnDownloadMulitUpdate, OnDownloadMulitComplete); } else { m_DownloadRoutineList.Remove(routine); GameEntry.Pool.EnqueueClassObject(routine); } m_DownloadMulitCurrCount++; if (m_OnDownloadMulitUpdate != null) { m_OnDownloadMulitUpdate(m_DownloadMulitCurrCount, m_DownloadMulitNeedCount, m_DownloadMulitCurrSize, m_DownloadMulitTotalSize); } if (m_DownloadMulitCurrCount == m_DownloadMulitNeedCount) { //结束的时候 直接把当前下载的大小设置为总大小 m_DownloadMulitCurrSize = m_DownloadMulitTotalSize; if (m_OnDownloadMulitUpdate != null) { m_OnDownloadMulitUpdate(m_DownloadMulitCurrCount, m_DownloadMulitNeedCount, m_DownloadMulitCurrSize, m_DownloadMulitTotalSize); } if (m_OnDownloadMulitComplete != null) { m_OnDownloadMulitComplete(); } } }
/// <summary> /// 下载初始资源 /// </summary> private void DownloadInitResources() { GameEntry.Event.CommonEvent.Dispatch(SysEventId.CheckVersionBeginDownload); m_DownloadingParams = GameEntry.Pool.DequeueClassObject <BaseParams>(); m_DownloadingParams.Reset(); m_NeedDownloadList.Clear(); var enumerator = m_CNDVersionDic.GetEnumerator(); while (enumerator.MoveNext()) { AssetBundleInfoEntity entity = enumerator.Current.Value; if (entity.IsFirstData) { m_NeedDownloadList.AddLast(entity.AssetBundleName); } } GameEntry.Download.BeginDownloadMulit(m_NeedDownloadList, OnDownloadMulitUpdate, OnDownloadMulitComplete); }
/// <summary> /// 下载单一文件 /// </summary> /// <param name="url"></param> /// <param name="onUpdate"></param> /// <param name="onComplete"></param> public void BeginDownloadSingle(string url, BaseAction <string, ulong, float> onUpdate = null, BaseAction <string> onComplete = null) { AssetBundleInfoEntity entity = GameEntry.Resource.ResourceManager.GetAssetBundleInfo(url); if (entity == null) { GameEntry.LogError("无效资源包=>" + url); return; } DownloadRoutine routine = GameEntry.Pool.DequeueClassObject <DownloadRoutine>(); routine.BeginDownload(url, entity, onUpdate, onComplete: (string fileUrl, DownloadRoutine r) => { m_DownloadRoutineList.Remove(r); GameEntry.Pool.EnqueueClassObject(routine); if (onComplete != null) { onComplete(fileUrl); } }); m_DownloadRoutineList.AddLast(routine); }
/// <summary> /// 开始检查更新 /// </summary> private void BeginCheckVersionChange() { m_DownloadingParams = GameEntry.Pool.DequeueClassObject <BaseParams>(); m_DownloadingParams.Reset(); //需要删除的文件 LinkedList <string> delList = new LinkedList <string>(); //可写区资源MD5和CDN资源MD5不一致的文件 LinkedList <string> inconformityList = new LinkedList <string>(); LinkedList <string> needDownloadList = new LinkedList <string>(); #region 找出需要删除的文件进行删除 var enumerator = m_LocalAssetsVersionDic.GetEnumerator(); while (enumerator.MoveNext()) { string assetBundleName = enumerator.Current.Key; //去CDN对比 AssetBundleInfoEntity cdnAssetBundleInfo = null; if (m_CNDVersionDic.TryGetValue(assetBundleName, out cdnAssetBundleInfo)) { //可写区有 CDN也有 if (!cdnAssetBundleInfo.MD5.Equals(enumerator.Current.Value.MD5, StringComparison.CurrentCultureIgnoreCase)) { //如果MD5不一致 加入不一致链表 inconformityList.AddLast(assetBundleName); } } else { //可写区有 CDN上没有 加入删除列表 delList.AddLast(assetBundleName); } } //循环判断这个文件在只读区的MD5和CDN是否一致 一致的进行删除 不一致的进行重新下载 LinkedListNode <string> currInconformity = inconformityList.First; while (currInconformity != null) { AssetBundleInfoEntity cdnAssetBundleInfo = null; m_CNDVersionDic.TryGetValue(currInconformity.Value, out cdnAssetBundleInfo); AssetBundleInfoEntity streamingAssetsAssetBundleInfo = null; if (m_StreamingAssetsVersionDic != null) { m_StreamingAssetsVersionDic.TryGetValue(currInconformity.Value, out streamingAssetsAssetBundleInfo); } if (streamingAssetsAssetBundleInfo == null) { //如果只读区 没有 needDownloadList.AddLast(currInconformity.Value); } else { //判断 是否一致 if (cdnAssetBundleInfo.MD5.Equals(streamingAssetsAssetBundleInfo.MD5, StringComparison.CurrentCultureIgnoreCase)) { //一致 delList.AddLast(currInconformity.Value); } else { //不一致 needDownloadList.AddLast(currInconformity.Value); } } currInconformity = currInconformity.Next; } #endregion #region 除需要删除的 LinkedListNode <string> currDel = delList.First; while (currDel != null) { string filePath = string.Format("{0}/{1}", GameEntry.Resource.LocalFilePath, currDel.Value); if (File.Exists(filePath)) { File.Delete(filePath); } LinkedListNode <string> next = currDel.Next; delList.Remove(currDel); currDel = next; } #endregion #region 检查需要下载的 enumerator = m_CNDVersionDic.GetEnumerator(); while (enumerator.MoveNext()) { AssetBundleInfoEntity cdnAssetBundleInfo = enumerator.Current.Value; if (cdnAssetBundleInfo.IsFirstData) { //检查初始资源 if (!m_LocalAssetsVersionDic.ContainsKey(cdnAssetBundleInfo.AssetBundleName)) { //如果可写区没有 则去只读区判断一次 AssetBundleInfoEntity streamingAssetsAssetBundleInfo = null; if (m_StreamingAssetsVersionDic != null) { m_StreamingAssetsVersionDic.TryGetValue(cdnAssetBundleInfo.AssetBundleName, out streamingAssetsAssetBundleInfo); } if (streamingAssetsAssetBundleInfo == null) { //只读区不存在 needDownloadList.AddLast(cdnAssetBundleInfo.AssetBundleName); } else { //只读区存在 验证MD5 if (!cdnAssetBundleInfo.MD5.Equals(streamingAssetsAssetBundleInfo.MD5, StringComparison.CurrentCultureIgnoreCase)) { //MD5不一致 needDownloadList.AddLast(cdnAssetBundleInfo.AssetBundleName); } } } } } #endregion GameEntry.Event.CommonEvent.Dispatch(SysEventId.CheckVersionBeginDownload); //进行下载 GameEntry.Download.BeginDownloadMulit(needDownloadList, OnDownloadMulitUpdate, OnDownloadMulitComplete); }