Unity AssetBundle打包工具示例詳解
Unity批量打AB包
為瞭資源熱更新,Unity支持將所有資源打包成AssetBundle資源,存放在SteamingAssets文件夾中;
在項目發佈之前,需要將所有資源打包成.ab文件,動態加載;
在項目更新時,替換.ab資源文件,即可完成熱更新;
ab文件在加載時,會多一步解壓縮的過程,會增加性能消耗;
打包操作屬於編輯器拓展,所有腳本放在Eidtor文件夾下;
1.PathTool
根據不同平臺,獲取ab輸出和輸入路徑;
不同平臺的輸入輸出路徑不相同,ios,android,windows;《Unity資源文件夾介紹》
public class PathTools { // 打包AB包根路徑 public const string AB_RESOURCES = "StreamingAssets"; // 得到 AB 資源的輸入目錄 public static string GetABResourcesPath() { return Application.dataPath + "/" + AB_RESOURCES; } // 獲得 AB 包輸出路徑 public static string GetABOutPath() { return GetPlatformPath() + "/" + GetPlatformName(); } //獲得平臺路徑 private static string GetPlatformPath() { string strReturenPlatformPath = string.Empty; #if UNITY_STANDALONE_WIN strReturenPlatformPath = Application.streamingAssetsPath; #elif UNITY_IPHONE strReturenPlatformPath = Application.persistentDataPath; #elif UNITY_ANDROID strReturenPlatformPath = Application.persistentDataPath; #endif return strReturenPlatformPath; } // 獲得平臺名稱 public static string GetPlatformName() { string strReturenPlatformName = string.Empty; #if UNITY_STANDALONE_WIN strReturenPlatformName = "Windows"; #elif UNITY_IPHONE strReturenPlatformName = "IPhone"; #elif UNITY_ANDROID strReturenPlatformName = "Android"; #endif return strReturenPlatformName; } // 返回 WWW 下載 AB 包加載路徑 public static string GetWWWAssetBundlePath() { string strReturnWWWPath = string.Empty; #if UNITY_STANDALONE_WIN strReturnWWWPath = "file://" + GetABOutPath(); #elif UNITY_IPHONE strReturnWWWPath = GetABOutPath() + "/Raw/"; #elif UNITY_ANDROID strReturnWWWPath = "jar:file://" + GetABOutPath(); #endif return strReturnWWWPath; } }
2.CreateAB
功能:選中一個文件夾,將該文件夾中所有資源文件打包成AB文件;
主要邏輯:遍歷文件夾中所有文件,是文件的生成AssetBundleBuild存在鏈表中統一打包,是文件夾的遞歸上一步操作,將所有資源文件都放在listassets鏈表中;
官方Api:BuildPipeline.BuildAssetBundles統一打包所有資源;
public class CreateAB : MonoBehaviour { private static string abOutPath; private static List<AssetBundleBuild> listassets = new List<AssetBundleBuild>(); private static List<DirectoryInfo> listfileinfo = new List<DirectoryInfo>(); private static bool isover = false; //是否檢查完成,可以打包 static private string selectPath; public static bool GetState() { return isover; } public static AssetBundleBuild[] GetAssetBundleBuilds() { return listassets.ToArray(); } [MenuItem("ABTools/CreatAB &_Q", false)] public static void CreateModelAB() { abOutPath = Application.streamingAssetsPath; if (!Directory.Exists(abOutPath)) Directory.CreateDirectory(abOutPath); UnityEngine.Object obj = Selection.activeObject; selectPath = AssetDatabase.GetAssetPath(obj); SearchFileAssetBundleBuild(selectPath); BuildPipeline.BuildAssetBundles(abOutPath, CreateAB.GetAssetBundleBuilds(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget); Debug.Log("AssetBundle打包完畢"); } [MenuItem("ABTools/CreatAB &_Q", true)] public static bool CanCreatAB() { if (Selection.objects.Length > 0) { return true; } else return false; }
這裡為什麼會紅我也不知道…
//是文件,繼續向下 public static void SearchFileAssetBundleBuild(string path) { DirectoryInfo directory = new DirectoryInfo(@path); FileSystemInfo[] fileSystemInfos = directory.GetFileSystemInfos(); listfileinfo.Clear(); //遍歷所有文件夾中所有文件 foreach (var item in fileSystemInfos) { int idx = item.ToString().LastIndexOf(@"\"); string name = item.ToString().Substring(idx + 1); //item為文件夾,添加進listfileinfo,遞歸調用 if ((item as DirectoryInfo) != null) listfileinfo.Add(item as DirectoryInfo); //剔除meta文件,其他文件都創建AssetBundleBuild,添加進listassets; if (!name.Contains(".meta")) { CheckFileOrDirectoryReturnBundleName(item, path + "/" + name); } } if (listfileinfo.Count == 0) isover = true; else { Debug.LogError(listfileinfo.Count); } } //判斷是文件還是文件夾 public static string CheckFileOrDirectoryReturnBundleName(FileSystemInfo fileSystemInfo, string path) { FileInfo fileInfo = fileSystemInfo as FileInfo; if (fileInfo != null) { string[] strs = path.Split('.'); string[] dictors = strs[0].Split('/'); string name = ""; for (int i = 1; i < dictors.Length; i++) { if (i < dictors.Length - 1) { name += dictors[i] + "/"; } else { name += dictors[i]; } } string[] strName = selectPath.Split('/'); AssetBundleBuild assetBundleBuild = new AssetBundleBuild(); assetBundleBuild.assetBundleName = strName[strName.Length - 1]; assetBundleBuild.assetBundleVariant = "ab"; assetBundleBuild.assetNames = new string[] {path}; listassets.Add(assetBundleBuild); return name; } else { //遞歸調用 SearchFileAssetBundleBuild(path); return null; } } }
3.ClearABLable
打包時每個資源會添加一個標簽,如果重復打包,需要清空才可再次打包,否則會失敗;
使用官方API:AssetDatabase.RemoveUnusedAssetBundleNames();
因為註釋寫的很詳細,就不贅述瞭;
public class ClearABLable { [MenuItem("ABTools/Remove AB Label")] public static void RemoveABLabel() { // 需要移除標記的根目錄 string strNeedRemoveLabelRoot = string.Empty; // 目錄信息(場景目錄信息數組,表示所有根目錄下場景目錄) DirectoryInfo[] directoryDIRArray = null; // 定義需要移除AB標簽的資源的文件夾根目錄 strNeedRemoveLabelRoot = PathTools.GetABResourcesPath(); DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedRemoveLabelRoot); directoryDIRArray = dirTempInfo.GetDirectories(); // 遍歷本場景目錄下所有的目錄或者文件 foreach (DirectoryInfo currentDir in directoryDIRArray) { // 遞歸調用方法,找到文件,則使用 AssetImporter 類,標記“包名”與 “後綴名” JudgeDirOrFileByRecursive(currentDir); } // 清空無用的 AB 標記 AssetDatabase.RemoveUnusedAssetBundleNames(); // 刷新 AssetDatabase.Refresh(); // 提示信息,標記包名完成 Debug.Log("AssetBundle 本次操作移除標記完成"); } /// <summary> /// 遞歸判斷判斷是否是目錄或文件 /// 是文件,修改 Asset Bundle 標記 /// 是目錄,則繼續遞歸 /// </summary> /// <param name="fileSystemInfo">當前文件信息(文件信息與目錄信息可以相互轉換)</param> private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo) { // 參數檢查 if (fileSystemInfo.Exists == false) { Debug.LogError("文件或者目錄名稱:" + fileSystemInfo + " 不存在,請檢查"); return; } // 得到當前目錄下一級的文件信息集合 DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo; // 文件信息轉為目錄信息 FileSystemInfo[] fileSystemInfoArray = directoryInfoObj.GetFileSystemInfos(); foreach (FileSystemInfo fileInfo in fileSystemInfoArray) { FileInfo fileInfoObj = fileInfo as FileInfo; // 文件類型 if (fileInfoObj != null) { // 修改此文件的 AssetBundle 標簽 RemoveFileABLabel(fileInfoObj); } // 目錄類型 else { // 如果是目錄,則遞歸調用 JudgeDirOrFileByRecursive(fileInfo); } } } /// <summary> /// 給文件移除 Asset Bundle 標記 /// </summary> /// <param name="fileInfoObj">文件(文件信息)</param> static void RemoveFileABLabel(FileInfo fileInfoObj) { // AssetBundle 包名稱 string strABName = string.Empty; // 文件路徑(相對路徑) string strAssetFilePath = string.Empty; // 參數檢查(*.meta 文件不做處理) if (fileInfoObj.Extension == ".meta") { return; } // 得到 AB 包名稱 strABName = string.Empty; // 獲取資源文件的相對路徑 int tmpIndex = fileInfoObj.FullName.IndexOf("Assets"); // 得到文件相對路徑 strAssetFilePath = fileInfoObj.FullName.Substring(tmpIndex); // 給資源文件移除 AB 名稱 AssetImporter tmpImportObj = AssetImporter.GetAtPath(strAssetFilePath); tmpImportObj.assetBundleName = strABName; } }
4.拓展
更多的時候,我們打包需要一鍵打包,也可能需要多個文件打成一個ab包,隻需要修改一下文件邏輯即可;
打ab包本身並不復雜,對文件路徑字符串的處理比較多,多Debug調試;
到此這篇關於Unity AssetBundle打包工具的文章就介紹到這瞭,更多相關Unity AssetBundle打包內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Unity命令行打包WebGL的示例代碼
- Unity實現聊天室功能
- 擎動賦能跨端遊戲創作力,Unity即將亮相2021年ChinaJoy BTOB展區
- C#中的LINQ to Objects詳解(2)
- Unity同步/異步調用Android的方法實例