UNITY编辑器模式下static变量的坑
生活随笔
收集整理的這篇文章主要介紹了
UNITY编辑器模式下static变量的坑
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
UNITY編輯器模式下static變量的坑
在unity中寫編輯器擴展工具,如在編輯器中加個菜單,點擊這個菜單項時執行打包功能。
類如下,其中的靜態變量,如果每次進來不清空,則LIST會越來越大,打包函數執行完后系統不會幫我們清空
#if UNITY_EDITORusing System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEditor;using UnityEngine; using LitJson; using System.Security.Cryptography;//資源清單,列出了游戲中用到的所有資源 [Serializable] public class AssetsList {/*** 資源清單* <相對路徑, MD5串>*/public Dictionary<string, string> Assets2Md5 = new Dictionary<string, string>();//容量未設置,后面可以寫成常量,根據上次數據得出 }public class AssetBundleBuilder {public static string BundlePath = "";public static AssetsList AssetsList = new AssetsList();public static List<string> DependAssets_PathList = new List<string>(8000); //InGameRes所依賴的ArtSource等文件夾下的資源public static List<string> Assets_PathList = new List<string>(8000); //InGameRes文件夾下的資源public static List<AssetBundleBuild> BuildList = new List<AssetBundleBuild>(18000); //估計值,后面可以寫成常量,根據上次數據得出public static string ResRootPath = "Assets/Resources"; //資源目錄,根據此目錄查找所有依賴的資源public static string ResDependPath = "Assets/ArtSource"; //資源目錄,根據此目錄查找所有依賴的資源public static string ResFolder = "Resources"; //資源打包的依據文件夾,此文件夾下的所有文件及所有依賴文件都被打進AB包,不要在此文件夾下放備份或無用的資源public static string Depends_List_File = "Assets/depends_list.json";public static string Assets_List_File = "Assets/assets_list.json";public static int FileNumLimit = 10; //測試使用,只收集限定數量的文件public static void BuildAB(BuildTarget buildTarget){if (!Directory.Exists(ResRootPath)){Debug.LogError("資源目錄不存在:" + ResRootPath);return;}var files = Directory.GetFiles(ResRootPath, "*", SearchOption.AllDirectories);var stopwt = System.Diagnostics.Stopwatch.StartNew();var t1 = stopwt.ElapsedMilliseconds;/**** 坑,這里必須要清空,否則每次進來就會往Assets_PathList里添加一次內容*/BuildList.Clear();Assets_PathList.Clear();DependAssets_PathList.Clear();AssetsList.Assets2Md5.Clear();var infoTitle = "收集文件,目錄 : " + ResRootPath;//第一步,將ResRootPath目錄下的文件收集起來,此目錄的東西都是游戲中要用到的,此目錄之外的東西不一定會用到var idx = 0;for (int i=0, cnt=files.Length; i<cnt; ++i){var item = files[i];var ext = Path.GetExtension(item);if (string.Compare(ext, ".meta", true)==0 || string.Compare(ext, ".cs", true)==0)continue;if ((string.Compare(ext, ".prefab", true) == 0 || string.Compare(ext, ".mat", true) == 0|| string.Compare(ext, ".unity", true) == 0 || string.Compare(ext, ".controller", true) == 0)){idx++;if (idx > FileNumLimit)break;//添加到構建列表var abName = AddToBuildList(item);Assets_PathList.Add(abName);}EditorUtility.DisplayProgressBar(infoTitle, item, i * 1.0f / cnt);}WriteToJson(Assets_List_File, Assets_PathList);//第二步,將ResRootPath依賴的文件收集進來 CheckAllDepends(files);var infoTitle2 = "收集依賴,目錄 : " + ResDependPath;for (int i = 0, cnt = DependAssets_PathList.Count; i < cnt; ++i){var item = DependAssets_PathList[i];//添加到構建列表 AddToBuildList(item);EditorUtility.DisplayProgressBar(infoTitle2, item, i * 1.0f / cnt);}//第三步,增量打包var targetName = buildTarget == BuildTarget.iOS ? "IOS" : "Android";BundlePath = Application.dataPath.Substring(0, Application.dataPath.Length-6) + "Bundles" + targetName; //放到Assets同目錄if (!Directory.Exists(BundlePath)){Directory.CreateDirectory(BundlePath);}var dt1 = stopwt.ElapsedMilliseconds - t1;ClearUnusedBundles(files);/**** 一次傳入所有需要打包的數據,UNITY會保證它們之間的依賴被正確處理:先打被依賴的包,再打自己* 我們必須保證傳入數據的完全,如果被依賴的包不在我們傳入的列表中,則相應資源會被打到所有用到該包的包中,造成資源的重復包含*/AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(BundlePath, BuildList.ToArray(), BuildAssetBundleOptions.ChunkBasedCompression, buildTarget);EditorUtility.ClearProgressBar();var dt2 = stopwt.ElapsedMilliseconds - t1 - dt1;EditorUtility.DisplayDialog("打包完成", "耗時:" + dt1 / 1000.0f + " + " + dt2/1000.0f + "\n路徑:" + BundlePath, "ok");GenResList(manifest);EditorUtility.UnloadUnusedAssetsImmediate();}public static string AddToBuildList(string resPath){var relativeDir = resPath;//不能這樣處理,因為可能有同名卻不同后綴的文件存在//relativeDir = relativeDir.Substring(0, relativeDir.LastIndexOf(".")); //去除后綴relativeDir = relativeDir.Replace("\\", "/");var abBuild = new AssetBundleBuild();abBuild.assetBundleName = relativeDir;abBuild.assetNames = new string[] { resPath };abBuild.assetBundleVariant = "ab";BuildList.Add(abBuild);return relativeDir;}//將AB包移動到StreamingAssets目錄下,為打APK或IPA作準備public static void CopyToStreamingAssets(BuildTarget buildTarget){CopyFolder(BundlePath, Application.streamingAssetsPath + "/Bundles/");}/**** 增量打包的關鍵,遍歷上次打出的包,與本次【構建列表BuildList】里的內容對比,不在列表中的刪除掉。* 在列表中的保留不變。這樣當我們再次執行打包操作時,如果文件對應的AB包已存在且文件沒有更改,則不用重新打包*/public static void ClearUnusedBundles(string[] files){if (!Directory.Exists(BundlePath)){Debug.LogError("包目錄不存在:" + BundlePath);return;}var abFiles = Directory.GetFiles(BundlePath + "/assets", "*", SearchOption.AllDirectories);var delList = new List<string>();for (int i=0, n=abFiles.Length; i<n; ++i){var ext = Path.GetExtension(abFiles[i]);var file = Path.ChangeExtension(abFiles[i], null);if(string.Compare(ext, ".manifest", true) == 0){file = Path.ChangeExtension(file, null);}file = file.Substring(file.IndexOf("assets", StringComparison.CurrentCultureIgnoreCase));if (!File.Exists(file)){delList.Add(abFiles[i]);}EditorUtility.DisplayProgressBar("正在檢查AssetBundle", file, i * 1.0f / n);}for (int i=0, n= delList.Count; i<n; ++i){EditorUtility.DisplayProgressBar("正在清理無用的AssetBundle", delList[i], i * 1.0f / n);if (!File.Exists(delList[i])){EditorUtility.DisplayDialog("", "不存在此文件", "ok");continue;}File.Delete(delList[i]);}EditorUtility.ClearProgressBar();WriteToJson("Assets/delete_list.json", delList);}//剪切到某個目錄,并重命名public static void MoveFolder(string src, string dest){if (Directory.Exists(dest)){Directory.Delete(dest, true);}Directory.CreateDirectory(dest);File.Move(src, dest + "/Bundles");}//復制到某個目錄,并重命名public static void CopyFolder(string src, string dest){if (Directory.Exists(dest)){Directory.Delete(dest, true);}Directory.CreateDirectory(dest);foreach (var sub in Directory.GetDirectories(src)){CopyFolder(sub + "/", dest + Path.GetFileName(sub) + "/");}foreach (var file in Directory.GetFiles(src)){File.Copy(file, dest + Path.GetFileName(file));}}/*** 生成資源清單* 格式:MD5 : 相對于/Bundles/的路徑* 作用:熱更的對比依據,通過MD5對比,確定文件的增-刪-修改*/public static void GenResList(AssetBundleManifest manifest){AssetsList.Assets2Md5.Clear();var abs = manifest.GetAllAssetBundles();foreach (var ab in abs){var hashes = manifest.GetAssetBundleHash(ab);AssetsList.Assets2Md5.Add(ab, hashes.ToString());}var writer = new JsonWriter();writer.PrettyPrint = true;JsonMapper.ToJson(AssetsList, writer);File.WriteAllText(BundlePath + "/asset_list.json", writer.ToString(), System.Text.Encoding.ASCII);}public static void DeleteBundles(BuildTarget target){var path = Application.dataPath + "/../" + (target == BuildTarget.Android ? "BundlesAndroid" : "BundlesIOS");var msg = "文件夾不存在" + " " + path;if (Directory.Exists(path)){Directory.Delete(path, true);msg = "清理完成";}EditorUtility.DisplayDialog("清理", msg, "ok");}//得到指定文件夾下資源的所有依賴public static void CheckAllDepends(string targetPath){if (!Directory.Exists(targetPath)){Debug.LogError("資源目錄不存在:" + targetPath);return;}var files = Directory.GetFiles(targetPath, "*", SearchOption.AllDirectories);CheckAllDepends(files);}//得到指定文件的所有依賴public static void CheckAllDepends(string[] files){var stopWatch = System.Diagnostics.Stopwatch.StartNew();var startTime = stopWatch.ElapsedMilliseconds;DependAssets_PathList.Clear();var idx = 0;for(int i=0, fileNum = files.Length; i< fileNum; ++i){var item = files[i];var ext = Path.GetExtension(item);if (string.Compare(ext, ".meta", true) == 0 || string.Compare(ext, ".cs",true) == 0)continue;if ((string.Compare(ext, ".prefab", true) == 0 || string.Compare(ext, ".mat", true) == 0|| string.Compare(ext, ".unity", true) == 0 || string.Compare(ext, ".controller", true) == 0)){idx++;if (idx > FileNumLimit)break;var dpends = AssetDatabase.GetDependencies(item, true);foreach (var s in dpends){if (s.Contains(ResFolder) || s.Contains(".cs"))continue;//var substr = s.Substring(s.IndexOf("Assets/"));if (!DependAssets_PathList.Contains(s)){DependAssets_PathList.Add(s);}}}var progress = i *1.0f/ fileNum;EditorUtility.DisplayProgressBar("正在查找引用" + fileNum, item, progress);}EditorUtility.ClearProgressBar();//var savePath = "Assets/refs_list.json"; WriteToJson(Depends_List_File, DependAssets_PathList);var deltaTime = stopWatch.ElapsedMilliseconds - startTime;EditorUtility.DisplayDialog("檢查完成", "耗時" + deltaTime/1000.0f + "\n保存路徑: " + Depends_List_File, "ok");}public static void WriteToJson(string path, object obj){var writer = new JsonWriter();writer.PrettyPrint = true;JsonMapper.ToJson(obj, writer);File.WriteAllText(path, writer.ToString());}[MenuItem("AssetBundle/安卓/構建AB包")]public static void BuildAndroidAB(){BuildAB(BuildTarget.Android);}[MenuItem("AssetBundle/IOS/構建AB包")]public static void BuildIOSAB(){BuildAB(BuildTarget.iOS);}[MenuItem("AssetBundle/安卓一鍵打包")]public static void AndroidOneKeyBuild(){BuildAB(BuildTarget.Android);CopyToStreamingAssets(BuildTarget.Android);}[MenuItem("AssetBundle/IOS一鍵打包")]public static void IOSOneKeyBuild(){BuildAB(BuildTarget.iOS);CopyToStreamingAssets(BuildTarget.iOS);}[MenuItem("AssetBundle/安卓/拷到StreamingAssets目錄")]public static void CopyAndroidABToStreamingAssets(){CopyToStreamingAssets(BuildTarget.Android);}[MenuItem("AssetBundle/IOS/拷到StreamingAssets目錄")]public static void CopyIOSABToStreamingAssets(){CopyToStreamingAssets(BuildTarget.iOS);}[MenuItem("AssetBundle/清理/清理安卓包")]public static void DeleteAndroidABs(){DeleteBundles(BuildTarget.Android);}[MenuItem("AssetBundle/清理/清理蘋果包")]public static void DeleteIOSABs(){DeleteBundles(BuildTarget.iOS);}[MenuItem("AssetBundle/資源檢查/檢查依賴")]public static void CheckAssetsDepends(){CheckAllDepends(ResRootPath);} }#endif?
posted on 2019-06-14 16:48 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏
總結
以上是生活随笔為你收集整理的UNITY编辑器模式下static变量的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 预置体很大的原因
- 下一篇: UNITY崩溃的日志