/// <summary> /// 加载AB配置表 /// </summary> /// <returns></returns> public bool LoadAssetBundleConfig(bool isInit = true) { AssetBundleConfig abConfig = null; #if UNITY_EDITOR if (ResourceManager.Instance.m_LoadFromAssetBundle) { #endif //初始化时候的ab配置文件在streamingAssets文件夹中 string configPath = Application.streamingAssetsPath + "/" + m_ABConfigABName; //非初始化,检查热更后进来的 if (!isInit) { //热更完毕后检查配置文件是否热更了 string hotABPath = HotPatchManager.Instance.ComputeABPath(m_ABConfigABName); if (string.IsNullOrEmpty(hotABPath)) { return(true); } else { //文件改变了,卸载本地的ab包,从热更路径下下载新的ab包 if (configAB != null) { configAB.Unload(true); configPath = hotABPath; } } } m_AssetBundleInfoDic.Clear(); //加密后的ab包要先解密,才能加载 if (Encrypt) { byte[] bytes = AES.AESFileByteDecrypt(configPath, FrameConstr.m_ABSecretKey); configAB = AssetBundle.LoadFromMemory(bytes); } else { configAB = AssetBundle.LoadFromFile(configPath); } TextAsset textAsset = configAB.LoadAsset <TextAsset>(m_ABConfigABName); if (textAsset == null) { Debug.LogError("AssetBundleConfig is no exist!"); return(false); } //创建一个内存流 MemoryStream stream = new MemoryStream(textAsset.bytes); //二进制序列化对象 BinaryFormatter bf = new BinaryFormatter(); abConfig = (AssetBundleConfig)bf.Deserialize(stream); //关闭内存流 stream.Close(); #if UNITY_EDITOR } else { m_AssetBundleInfoDic.Clear(); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(Application.dataPath + "/AssetBundleConfig.xml"); XmlSerializer xs = new XmlSerializer(typeof(AssetBundleConfig)); StringReader sr = new StringReader(xmlDoc.InnerXml); abConfig = (AssetBundleConfig)xs.Deserialize(sr); } #endif for (int i = 0; i < abConfig.ABList.Count; ++i) { ABBase abBase = abConfig.ABList[i]; AssetBundleInfo abInfo = new AssetBundleInfo(); abInfo.m_Crc = abBase.Crc; abInfo.m_AssetName = abBase.AssetName; abInfo.m_ABName = abBase.ABName; abInfo.m_DependceAssetBundle = abBase.ABDependce; if (m_AssetBundleInfoDic.ContainsKey(abInfo.m_Crc)) { Debug.LogError("重复的Crc : 资源名:" + abInfo.m_AssetName + " ab包名:" + abInfo.m_ABName); } else { m_AssetBundleInfoDic.Add(abInfo.m_Crc, abInfo); } } return(true); }
/// <summary> /// 写入配置文件 /// </summary> static void WriteData() { //记录所有即将打包的资源文件路径和它的包名,用来生成配置文件用的 //key是资源文件路径,value是资源文件包名,属于哪一个ab包 Dictionary <string, string> resPathDic = new Dictionary <string, string>(); //获取所有的被标记为要打AB包的资源文件 string[] allBundles = AssetDatabase.GetAllAssetBundleNames(); for (int i = 0; i < allBundles.Length; ++i) { //根据assetBundle的名字获取assetBundle的全路径 string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]); for (int j = 0; j < allBundlePath.Length; j++) { //过滤assetBundle文件中的脚本文件 if (allBundlePath[j].EndsWith(".cs")) { continue; } resPathDic.Add(allBundlePath[j], allBundles[i]); Debug.Log("此AB包:" + allBundles[i] + "==下面包含的资源文件路径" + allBundlePath[j]); } } //创建一个AB配置文件 AssetBundleConfig config = new AssetBundleConfig(); //记录AB文件列表 config.ABList = new List <ABBase>(); //遍历所有的资源文件字典, foreach (var path in resPathDic.Keys) { //判断是否是有效路径 if (!ValidPath(path)) { continue; } ABBase abBase = new ABBase(); abBase.Path = path; abBase.Crc = Crc32.GetCrc32(path); //Crc加密 abBase.ABName = resPathDic[path]; //ab包名 abBase.AssetName = path.Remove(0, path.LastIndexOf("/") + 1); //截掉最后一个/,得到资源文件名称 Debug.Log("abBase.AssetName" + abBase.AssetName); abBase.ABDependce = new List <string>(); //获取这个资源文件的所有依赖项 string[] resDependce = AssetDatabase.GetDependencies(path); for (int i = 0; i < resDependce.Length; i++) { string resDependcePath = resDependce[i]; //依赖资源的路径 //去掉这个资源文件自己和cs文件 if (resDependcePath == path || path.EndsWith(".cs")) { continue; } string abName = string.Empty; //通过依赖资源的路径获取这个依赖资源的包名 if (resPathDic.TryGetValue(resDependcePath, out abName)) { //依赖资源的包名和自己本身资源在同一个包不管 if (abName == resPathDic[path]) { continue; } //将这个包名添加到这个资源的依赖列表中, //可能这个资源的多个依赖资源在同一个包中 //所以只添加一次就够了 if (!abBase.ABDependce.Contains(abName)) { abBase.ABDependce.Add(abName); } } } config.ABList.Add(abBase); } //写入xml string xmlPath = Application.dataPath + "/AssetBundleConfig.xml"; if (File.Exists(xmlPath)) { File.Delete(xmlPath); } using (FileStream fileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { using (StreamWriter sw = new StreamWriter(fileStream, System.Text.Encoding.UTF8)) { XmlSerializer xs = new XmlSerializer(config.GetType()); xs.Serialize(sw, config); } } //写入二进制 foreach (ABBase abBase in config.ABList) { abBase.Path = ""; } //提前在ABBYTEPATH这个路径下创建一个2进制文件,将前面收集到的要打包的文件信息写入这个2进制文件 //创建一个文件流对象 using (FileStream fs = new FileStream(ABBYTEPATH, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { fs.Seek(0, SeekOrigin.Begin); fs.SetLength(0); //二进制序列化对象 BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, config); fs.Close(); } //刷新 AssetDatabase.Refresh(); //设置这个2进制文件也打包 SetABName("assetbundleconfig", ABBYTEPATH); }