本篇接着上一篇。上篇中說到的4步的代碼分別如下所示:
(1)將資源打包成assetbundle,並放到自定目錄下
using UnityEditor; using UnityEngine; using System.IO; using System.Collections; using System.Collections.Generic; public class CreateAssetBundle { public static void Execute(UnityEditor.BuildTarget target) { string SavePath = AssetBundleController.GetPlatformPath(target); // 當前選中的資源列表 foreach (Object o in Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)) { string path = AssetDatabase.GetAssetPath(o); // 過濾掉meta文件和文件夾 if(path.Contains(".meta") || path.Contains(".") == false) continue; // 過濾掉UIAtlas目錄下的貼圖和材質(UI/Common目錄下的所有資源都是UIAtlas) if (path.Contains("UI/Common")) { if ((o is Texture) || (o is Material)) continue; } path = SavePath + ConvertToAssetBundleName(path); path = path.Substring(0, path.LastIndexOf('.')); path += ".assetbundle"; BuildPipeline.BuildAssetBundle(o, null, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.DeterministicAssetBundle, target); } // scene目錄下的資源 AssetDatabase.Refresh(); } static string ConvertToAssetBundleName(string ResName) { return ResName.Replace('/', '.'); }
}
(2)為每個assetbund生成MD5碼,用於檢查資源是否有修改
using UnityEngine; using UnityEditor; using System.IO; using System.Xml; using System.Collections; using System.Collections.Generic; using System.Security.Cryptography; public class CreateMD5List { public static void Execute(UnityEditor.BuildTarget target) { string platform = AssetBundleController.GetPlatformName(target); Execute(platform); AssetDatabase.Refresh(); } public static void Execute(string platform) { Dictionary<string, string> DicFileMD5 = new Dictionary<string, string>(); MD5CryptoServiceProvider md5Generator = new MD5CryptoServiceProvider(); string dir = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform); foreach (string filePath in Directory.GetFiles(dir)) { if (filePath.Contains(".meta") || filePath.Contains("VersionMD5") || filePath.Contains(".xml")) continue; FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] hash = md5Generator.ComputeHash(file); string strMD5 = System.BitConverter.ToString(hash); file.Close(); string key = filePath.Substring(dir.Length + 1, filePath.Length - dir.Length - 1); if (DicFileMD5.ContainsKey(key) == false) DicFileMD5.Add(key, strMD5); else Debug.LogWarning("<Two File has the same name> name = " + filePath); } string savePath = System.IO.Path.Combine(Application.dataPath, "AssetBundle/") + platform + "/VersionNum"; if (Directory.Exists(savePath) == false) Directory.CreateDirectory(savePath); // 刪除前一版的old數據 if (File.Exists(savePath + "/VersionMD5-old.xml")) { System.IO.File.Delete(savePath + "/VersionMD5-old.xml"); } // 如果之前的版本存在,則將其名字改為VersionMD5-old.xml if (File.Exists(savePath + "/VersionMD5.xml")) { System.IO.File.Move(savePath + "/VersionMD5.xml", savePath + "/VersionMD5-old.xml"); } XmlDocument XmlDoc = new XmlDocument(); XmlElement XmlRoot = XmlDoc.CreateElement("Files"); XmlDoc.AppendChild(XmlRoot); foreach (KeyValuePair<string, string> pair in DicFileMD5) { XmlElement xmlElem = XmlDoc.CreateElement("File"); XmlRoot.AppendChild(xmlElem); xmlElem.SetAttribute("FileName", pair.Key); xmlElem.SetAttribute("MD5", pair.Value); } // 讀取舊版本的MD5 Dictionary<string, string> dicOldMD5 = ReadMD5File(savePath + "/VersionMD5-old.xml"); // VersionMD5-old中有,而VersionMD5中沒有的信息,手動添加到VersionMD5 foreach (KeyValuePair<string, string> pair in dicOldMD5) { if (DicFileMD5.ContainsKey(pair.Key) == false) DicFileMD5.Add(pair.Key, pair.Value); } XmlDoc.Save(savePath + "/VersionMD5.xml"); XmlDoc = null; } static Dictionary<string, string> ReadMD5File(string fileName) { Dictionary<string, string> DicMD5 = new Dictionary<string, string>(); // 如果文件不存在,則直接返回 if (System.IO.File.Exists(fileName) == false) return DicMD5; XmlDocument XmlDoc = new XmlDocument(); XmlDoc.Load(fileName); XmlElement XmlRoot = XmlDoc.DocumentElement; foreach (XmlNode node in XmlRoot.ChildNodes) { if ((node is XmlElement) == false) continue; string file = (node as XmlElement).GetAttribute("FileName"); string md5 = (node as XmlElement).GetAttribute("MD5"); if (DicMD5.ContainsKey(file) == false) { DicMD5.Add(file, md5); } } XmlRoot = null; XmlDoc = null; return DicMD5; }
}
MD5列表如下所示:
<Files> <File FileName="Assets.Resources.BigLevelTexture.TestLevel.assetbundle" MD5="54-00-42-38-D5-86-43-A6-57-9D-7C-09-3A-F8-6E-10" /> <File FileName="Assets.Resources.EquipmentTexture.Test001.assetbundle" MD5="A1-19-D4-04-17-94-18-61-60-99-35-25-3F-7C-39-93" /> <File FileName="Assets.Resources.EquipmentTexture.Test002.assetbundle" MD5="CF-36-DA-C8-D2-DB-CE-FD-4A-BF-31-81-A1-D1-D2-21" /> <File FileName="Assets.Resources.EquipmentTexture.Test003.assetbundle" MD5="EF-30-78-AE-F8-F4-A0-EC-5B-4E-45-3F-1E-EF-42-44" /> <File FileName="Assets.Resources.EquipmentTexture.Test004.assetbundle" MD5="3D-5D-A7-01-D2-B1-20-5F-B9-89-C5-CB-40-96-EC-89" /> <File FileName="Assets.Resources.PetTexture.Empty.assetbundle" MD5="D9-AC-54-F8-EB-AA-1C-36-8C-2B-6C-12-37-AB-3B-48" /> </Files>
(3)比較新舊MD5碼,生成資源變更列表
using UnityEngine; using UnityEditor; using System.IO; using System.Xml; using System.Collections; using System.Collections.Generic; public class CampareMD5ToGenerateVersionNum { public static void Execute(UnityEditor.BuildTarget target) { string platform = AssetBundleController.GetPlatformName(target); Execute(platform); AssetDatabase.Refresh(); } // 對比對應版本目錄下的VersionMD5和VersionMD5-old,得到最新的版本號文件VersionNum.xml public static void Execute(string platform) { // 讀取新舊MD5列表 string newVersionMD5 = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform + "/VersionNum/VersionMD5.xml"); string oldVersionMD5 = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform + "/VersionNum/VersionMD5-old.xml"); Dictionary<string, string> dicNewMD5Info = ReadMD5File(newVersionMD5); Dictionary<string, string> dicOldMD5Info = ReadMD5File(oldVersionMD5); // 讀取版本號記錄文件VersinNum.xml string oldVersionNum = System.IO.Path.Combine(Application.dataPath, "AssetBundle/" + platform + "/VersionNum/VersionNum.xml"); Dictionary<string, int> dicVersionNumInfo = ReadVersionNumFile(oldVersionNum); // 對比新舊MD5信息,並更新版本號,即對比dicNewMD5Info&&dicOldMD5Info來更新dicVersionNumInfo foreach (KeyValuePair<string, string> newPair in dicNewMD5Info) { // 舊版本中有 if (dicOldMD5Info.ContainsKey(newPair.Key)) { // MD5一樣,則不變 // MD5不一樣,則+1 // 容錯:如果新舊MD5都有,但是還沒有版本號記錄的,則直接添加新紀錄,並且將版本號設為1 if (dicVersionNumInfo.ContainsKey(newPair.Key) == false) { dicVersionNumInfo.Add(newPair.Key, 1); } else if (newPair.Value != dicOldMD5Info[newPair.Key]) { int num = dicVersionNumInfo[newPair.Key]; dicVersionNumInfo[newPair.Key] = num + 1; } } else // 舊版本中沒有,則添加新紀錄,並=1 { dicVersionNumInfo.Add(newPair.Key, 1); } } // 不可能出現舊版本中有,而新版本中沒有的情況,原因見生成MD5List的處理邏輯 // 存儲最新的VersionNum.xml SaveVersionNumFile(dicVersionNumInfo, oldVersionNum); } static Dictionary<string, string> ReadMD5File(string fileName) { Dictionary<string, string> DicMD5 = new Dictionary<string, string>(); // 如果文件不存在,則直接返回 if (System.IO.File.Exists(fileName) == false) return DicMD5; XmlDocument XmlDoc = new XmlDocument(); XmlDoc.Load(fileName); XmlElement XmlRoot = XmlDoc.DocumentElement; foreach (XmlNode node in XmlRoot.ChildNodes) { if ((node is XmlElement) == false) continue; string file = (node as XmlElement).GetAttribute("FileName"); string md5 = (node as XmlElement).GetAttribute("MD5"); if (DicMD5.ContainsKey(file) == false) { DicMD5.Add(file, md5); } } XmlRoot = null; XmlDoc = null; return DicMD5; } static Dictionary<string, int> ReadVersionNumFile(string fileName) { Dictionary<string, int> DicVersionNum = new Dictionary<string, int>(); // 如果文件不存在,則直接返回 if (System.IO.File.Exists(fileName) == false) return DicVersionNum; XmlDocument XmlDoc = new XmlDocument(); XmlDoc.Load(fileName); XmlElement XmlRoot = XmlDoc.DocumentElement; foreach (XmlNode node in XmlRoot.ChildNodes) { if ((node is XmlElement) == false) continue; string file = (node as XmlElement).GetAttribute("FileName"); int num = XmlConvert.ToInt32((node as XmlElement).GetAttribute("Num")); if (DicVersionNum.ContainsKey(file) == false) { DicVersionNum.Add(file, num); } } XmlRoot = null; XmlDoc = null; return DicVersionNum; } static void SaveVersionNumFile(Dictionary<string, int> data, string savePath) { XmlDocument XmlDoc = new XmlDocument(); XmlElement XmlRoot = XmlDoc.CreateElement("VersionNum"); XmlDoc.AppendChild(XmlRoot); foreach (KeyValuePair<string, int> pair in data) { XmlElement xmlElem = XmlDoc.CreateElement("File"); XmlRoot.AppendChild(xmlElem); xmlElem.SetAttribute("FileName", pair.Key); xmlElem.SetAttribute("Num", XmlConvert.ToString(pair.Value)); } XmlDoc.Save(savePath); XmlRoot = null; XmlDoc = null; }
}
如下圖所示,根據VersionMD5.xml和VersionMD5-old.xml對比產生VersionNum.xml:
(4)將變更列表文件也打包成assetbundle
也就是講VersionNum.xml打包后供下載:
using UnityEditor; using UnityEngine; using System.IO; using System.Collections; using System.Collections.Generic; public class CreateAssetBundleForXmlVersion { public static void Execute(UnityEditor.BuildTarget target) { string SavePath = AssetBundleController.GetPlatformPath(target); Object obj = AssetDatabase.LoadAssetAtPath(SavePath + "VersionNum/VersionNum.xml", typeof(Object)); BuildPipeline.BuildAssetBundle(obj, null, SavePath + "VersionNum/VersionNum.assetbundle", BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.DeterministicAssetBundle, target); AssetDatabase.Refresh(); } static string ConvertToAssetBundleName(string ResName) { return ResName.Replace('/', '.'); }
}