public void UpdateRes(Action <Boolean> _onCompleted) { Log.Debug("开始资源更新准备工作"); mOnUpdateCompleted = _onCompleted; var appConfigAb = AssetBundle.LoadFromFile( ResInfo.GetSystemApiLoadPath("res_config.grt", AssetLocation.StreamingPath)); if (appConfigAb == null) { Log.Critical(eLogType.Resources, "加载 In App res config 失败!!!"); appConfigAb.Unload(true); return; } mInAppConfig = ResConfigFile.Create(appConfigAb.LoadAsset <TextAsset>("res_config").bytes); if (appConfigAb == null) { Log.Critical(eLogType.Resources, "解析 In App res config 失败!!!"); appConfigAb.Unload(true); return; } appConfigAb.Unload(true); mLocalConfig = ResConfigFile.Create(ResInfo.GetSystemApiLoadPath("res_config", AssetLocation.PersistentPath), true); if (mLocalConfig == null) { Log.Critical(eLogType.Resources, "创建 Local res config 失败!!!"); return; } StartCoroutine(checkUpdate()); }
/// <summary> /// 打包,添加文件信息 /// </summary> public void BuidlerAndResInfo(String _root, String _name, Int32 _version) { String physics_path = String.Concat(_root, "/", _name); // 文件不存在则打包失败 if (!File.Exists(physics_path)) { throw new FileNotFoundException("[ResConfigFile.BuilderAndResInfo]: 文件 {0} 不存在!", physics_path); } // 获取校验码 Byte[] bytes = FileHelper.ReadAllBytesFromFile(physics_path); // 检查是否为assetbundle // res文件不验证,但却为Assetbundle String assetbundleFileHash = null; assetbundleFileHash = getAssetbundleFileHash(physics_path, _name); ResInfo res_info = new ResInfo(_name, bytes.Length, _version , SHA1Helper.GetSHA1Hash(bytes), MD5Helper.GetMD5Hash(bytes), 0 , AssetLocation.Void , assetbundleFileHash == null ? ResourceType.GrtPackage : ResourceType.AssetBundle); res_info.AssetBundleTypeTreeHash = assetbundleFileHash; AddOrUpdateResInfo(res_info); //Log.Info( "Build {0} Done! save to: {1}", _name, physics_path ); }
/// <summary> /// 保存资源文件 /// </summary> /// <param name="_data"></param> /// <param name="_bytes"></param> /// <returns></returns> private Boolean saveResourceFile(ResInfo _data, Byte[] _bytes) { try { String savePath = _data.SavePath; FileHelper.CreateDirectoryByFilePath(savePath); //Log.Debug( eLogType.Resources, "保存文件路径: {0}", _data.SavePath ); FileStream fs = File.Create(savePath); fs.Write(_bytes, 0, _bytes.Length); fs.Flush(); fs.Close(); #if UNITY_IPHONE iPhone.SetNoBackupFlag(savePath); #endif //下载成功,记录文件位置 ResInfo newRes = _data.Clone(); newRes.Location = AssetLocation.PersistentPath; mLocalConfig.AddOrUpdateResInfo(newRes); mLocalConfig.Save(); Log.Debug(eLogType.Resources, "成功下载并保存Asset: {0} update list 剩余: {1}", savePath, mUpdateList.Count); } catch (Exception ex) { Log.Error(eLogType.Resources, "下载文件保存失败: {0}\n 错误信息: {1}", _data.Name, ex.Message); return(false); } return(true); }
/// <summary> /// 检测文件本身是否需要更新 /// </summary> /// <param name="_correct_res_info"></param> /// <returns></returns> public Boolean NeedUpdate(ResInfo _correct_res_info) { return(Size != _correct_res_info.Size || Crc32 != _correct_res_info.Crc32 || Md5 != _correct_res_info.Md5 || Sha1 != _correct_res_info.Sha1); }
private IEnumerator downloadRes() { Int32 retryCount = 0; ResInfo firstErrorNode = null; LinkedListNode <ResInfo> node = mUpdateList.First; while (node != null) { if (firstErrorNode != null && node.Value == firstErrorNode) { if (retryCount++ > 2) { showDownloadFailTip(); yield break; } firstErrorNode = null; } String downloadUrl = node.Value.DownloadUrl; // 这个属性每次都会新创建 Log.Info(eLogType.Resources, "开始下载: {0}", downloadUrl); using (UnityWebRequest www = UnityWebRequest.Get(downloadUrl)) { yield return(www.Send()); if (!www.isError) { if (!saveResourceFile(node.Value, www.downloadHandler.data)) { mUpdateList.AddLast(node.Value); if (firstErrorNode == null) { firstErrorNode = node.Value; } } else { //更新下载进度 mDownloadedSize += www.downloadHandler.data.Length; //Single progress = (float)downloadsize / (float)m_update_total_size; //SignalSystem.FireSignal( SignalId.AssetUpdateLoading_UpdateProgress, progress, downloadsize, m_update_total_size ); } } else { Log.Error(eLogType.Resources, "下载文件失败: {0}\n错误信息: {1}", node.Value.Name, www.error); mUpdateList.AddLast(node.Value); if (firstErrorNode == null) { firstErrorNode = node.Value; } } } var tmp = node.Next; mUpdateList.Remove(node); node = tmp; } mOnUpdateCompleted(true); }
public void CopyTo(ResInfo _dest_res_info) { _dest_res_info.Name = Name; _dest_res_info.Size = Size; _dest_res_info.Version = Version; _dest_res_info.Sha1 = Sha1; _dest_res_info.Md5 = Md5; _dest_res_info.Crc32 = Crc32; _dest_res_info.Location = Location; _dest_res_info.ResType = ResType; }
Resource_Base _createResourceData(ResInfo _info) { switch (_info.ResType) { case ResourceType.AssetBundle: { return(new Resource_Assetbundle(_info)); } case ResourceType.GrtPackage: { return(new Resource_GrtPackage(_info)); } default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// 添加或更新资源 /// </summary> /// <param name="_new_res"></param> public void AddOrUpdateResInfo(ResInfo _new_res) { if (ResDictionary.ContainsKey(_new_res.Name)) { for (int i = 0; i < m_assets.Count; i++) { if (m_assets[i].Name.Equals(_new_res.Name, StringComparison.OrdinalIgnoreCase)) { m_assets[i] = _new_res; ResDictionary[_new_res.Name] = _new_res; break; } } } else { ResDictionary.Add(_new_res.Name, _new_res); m_assets.Add(_new_res); } }
/// <summary> /// 初始化ResourceManager, 加载包内和包外的res_config /// </summary> /// <param name="_action_initialized"></param> /// <returns></returns> private IEnumerator _asyncInitialize(Action <Boolean> _action_initialized) { String app_res_config_path = ResInfo.GetWWWLoadPath("res_config", AssetLocation.StreamingPath); Log.Debug(eLogType.Resources, app_res_config_path); using (WWW www = new WWW(app_res_config_path)) { yield return(www); if (!String.IsNullOrEmpty(www.error)) // 加载错误 { Log.Error(eLogType.Resources, "[ResourceManager]: In App res_config assetbundle 加载失败!: {0}", www.error); _action_initialized(false); yield break; } ResConfigFile app_res_config = ResConfigFile.Create(www.bytes); if (app_res_config == null) // 解析错误 { Log.Error(eLogType.Resources, "[ResourceManager]: In App res_config 解析错误!"); _action_initialized(false); yield break; } mLoadResConfig = ResConfigFile.Create(ResUtility.LocalResConfigPath, true); if (mLoadResConfig == null) // 保存用assetsconfig 创建或读取错误 { app_res_config = null; Log.Error(eLogType.Resources, "[ResouceManager]: Saved res_config file 创建或解析错误!"); _action_initialized(false); yield break; } _action_initialized(true); } }
protected Resource_Base(ResInfo _resouce_info) { ResouceInfo = _resouce_info; RefConut = 0; DeleteImmediately = _resouce_info.ResType != ResourceType.AssetBundle; }
public Resource_GrtPackage(ResInfo _res_info) : base(_res_info) { }
public Resource_Assetbundle(ResInfo _res_info) : base(_res_info) { }
/// <summary> /// 尝试获取AssetInfo /// </summary> /// <param name="_name">Asset名称</param> /// <param name="_res_info">返回的AssetInfo</param> /// <returns></returns> public Boolean TryGetAssetInfo(String _name, out ResInfo _res_info) { return(ResDictionary.TryGetValue(_name, out _res_info)); }
/// <summary> /// 反序列化ResouceConfigFile /// </summary> /// <param name="_file_path"></param> /// <param name="_bytes"></param> /// <param name="_create_if_err"></param> /// <returns></returns> private static ResConfigFile _deserialize(String _file_path, Byte[] _bytes, Boolean _create_if_err) { ResConfigFile res_config = new ResConfigFile() { m_file_path = _file_path }; try { using (MemoryStream memory_stream = new MemoryStream(_bytes)) { using (StreamReader reader = new StreamReader(memory_stream, Encoding.UTF8)) { if (!Equals(Encoding.UTF8, reader.CurrentEncoding)) { throw new ConfigFileNotUTF8("AssetsConfig file with {0} encoding not UTF-8!", reader.CurrentEncoding.EncodingName); } if (reader.EndOfStream) { return(res_config); } Int32 line_count = 0; while (!reader.EndOfStream) { String line = reader.ReadLine(); if (String.IsNullOrEmpty(line)) { continue; } line_count++; String[] parts = line.Split('\t'); //#if UNITY_EDITOR // if( parts.Length != 8 && parts.Length != 9 ) //#else // if( parts.Length != 8 ) //#endif // throw new Exception( "Assetsinfo size error" ); String name = parts[0]; Int64 size = Int64.Parse(parts[1], NumberStyles.None); Int32 version = Int32.Parse(parts[2]); AssetLocation location = Configuration.ParseEnum <AssetLocation>(parts[3]); String sha1 = parts[4]; String md5 = parts[5]; UInt32 crc32 = UInt32.Parse(parts[6], NumberStyles.None); ResourceType resource_type = Configuration.ParseEnum <ResourceType>(parts[7]); ResInfo res = new ResInfo(name, size, version, sha1, md5, crc32, location, resource_type); #if UNITY_EDITOR if (parts.Length == 9) { res.AssetBundleTypeTreeHash = parts[8]; } #endif // 处理版本号 if (version > res_config.ResVersion) { res_config.ResVersion = version; } res_config.m_assets.Add(res); } } } } catch (Exception e) { if (_create_if_err) { Log.Error("解析 AssetsConfig 文件失败! 创建新文件"); return(new ResConfigFile() { m_file_path = _file_path }); } Log.Error("解析 AssetsConfig 文件失败!\tMessage: {0}\nStackTrace: {1} {2}", e.Message, e.StackTrace, e.ToString()); res_config = null; } return(res_config); }