這篇總結主要是總結下資源的熱更新
前段時間閑來無事,狂擼了下項目的熱更新代碼,寫個筆記總結下吧
打包其實比較簡單,主要是項目結構的設計和文件目錄的處理比較麻煩。
先設計一個文件結構
--ABResource -- 所有資源打包的主目錄
//這些目錄是資源的大類
--UI -圖集,圖片icon資源等
--Module1
--Module2
--Module3
-Animation 動畫 animator等資源
--Module1
--Module2
--Module3
--Sound 聲音資源
--Module1
--Module2
--Module3
--Model 模型資源
--Map 地圖資源,場景相關的超級大圖
--Effect 特效類
--Audio 視頻類
文件結構的設計直接影響后期的開發效率,打包方式流程其實都知道,但是文件目錄結構設計的好,對項目的開發效率提升非常大,所有模塊對應的子文件夾名字盡量統一,方便開發的時候使用統一命名存取資源。減少邏輯成本!
打包唯一復雜的地方就是文件夾讀取,后綴名的轉換
關鍵是對這個結構體字段的理解 AssetBundleBuild
首先,每一個AssetBundleBuild都代表將要生成的一個ab文件
一個ab文件里面可以關聯N個資源,至於多少個資源,由AssetBundleBuild里面的assetNames決定,Unity會根據名字找到當前這個文件夾里面的資源,注意這里面的路徑都是Unity Asset開始的相對路徑,而C#的Path、Directory這些路徑獲取工具拿到的都是全局路徑,需要自己做轉換
AssetBundleBuild里面只有2個字段是比較重要的
AssetBundleBuild.assetBundleName --------這個字段決定了你這份ab文件生成的名字
AssetBundleBuild.assetNames --------這個字段決定了你這份ab文件里面包含了多少個資源
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEditor; using System.Linq; using System; public class BundelTest { private static Dictionary<string,AssetBundleBuild> modulAbDic = new Dictionary<string, AssetBundleBuild>(); Dictionary<string,AssetBundle> AllAb = new Dictionary<string, AssetBundle>(); /// <summary> /// 解析每個模塊 /// </summary> /// <param name="path"></param> public static void BuildAllBundle(string path) { //這里是采用上述的文件結構,所以做的3層遍歷,也可以做成遞歸的方式,讓其適用多個層級 // 判斷這個路徑是否存在 if (Directory.Exists(path)) { Directory.CreateDirectory(path); } string realPath = Path.Combine(Application.dataPath,path); string[] floderList = Directory.GetDirectories(realPath);//這個只能獲取當前層級的子層級,不能獲取嵌套的 for (int i = 0; i < floderList.Length; i++) { string[] fileNames = Directory.GetDirectories(floderList[i]);//這個文件夾下的所有的子文件夾 for (int a = 0; a < fileNames.Length; a++) { getBundls(fileNames[a]);//第一層文件夾下面的文件。不包括里面文件夾 } } } /// <summary> /// 解析模塊內的資源 /// </summary> /// <param name="path"></param> public static void getBundls(string modulePath) { modulePath = modulePath.Replace("\\","/"); //合並的路徑都是\\需要轉義 string[] flies = Directory.GetFiles(modulePath); if (flies.Length > 0 ) { for (int i = 0; i < flies.Length; i++) { //處理模塊內文件 string assetBundleName = flies[i].Replace(Application.dataPath+"/",""); string ralativePath = getRelativePah(flies[i]); string _abPath =ralativePath; string ext = Path.GetExtension(ralativePath); assetBundleName = assetBundleName.Replace(ext,"")+".ab"; if (ext != ".meta") { string name = Path.GetDirectoryName(ralativePath)+"/"+Path.GetFileNameWithoutExtension(ralativePath); //包的名字,這個名字包含了資源的路徑。 AssetBundleBuild build = new AssetBundleBuild() ; if (modulAbDic.ContainsKey(_abPath)) { if (modulAbDic.TryGetValue(_abPath,out build)) { build.assetBundleName = assetBundleName; build.assetNames = new string[]{ralativePath}; --這里是一個資源對應一個build 所以是固定的 modulAbDic[_abPath] = build; } } else { build.assetBundleName = assetBundleName; build.assetNames = new string[]{ralativePath}; modulAbDic.Add(_abPath,build); } } } } } /// <summary> /// 打包所有資源,每個資源打一份ab,方便進行差異化分析 /// </summary> public static void BuildAssetBundleForDic() { AssetBundleBuild[] builds = modulAbDic.Values.ToArray();
//輸出路徑可以自行選擇,這里是默認輸出在桌面 BuildPipeline.BuildAssetBundles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),"bundle"),builds,BuildAssetBundleOptions.DeterministicAssetBundle ,BuildTarget.StandaloneWindows64); } /// <summary> /// 獲取asset下的相對位置 /// </summary> public static string getRelativePah(string path) { string _path = path.Replace("\\","/"); return _path.Replace(Application.dataPath,"Assets"); } }