using LuaInterface; using MiniJSON; using NUnit.Framework; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using taurus.client; using taurus.unity; using UnityEditor; using UnityEngine; using static Codice.Client.Commands.WkTree.WorkspaceTreeNode; public class PackUtil { const string ART_DIR = "Assets/ART/"; const string RES_DIR = "Assets/Resources/"; public static string HOT_EXTEND_PATH = ""; public static string HOT_BASE_PATH = ""; static void __ClearAllAssetNames() { string[] assetBundleNames = AssetDatabase.GetAllAssetBundleNames(); if (assetBundleNames == null || assetBundleNames.Length <= 0) return; for (int i = 0; i < assetBundleNames.Length; ++i) { float process = ((float)i) / ((float)assetBundleNames.Length); EditorUtility.DisplayProgressBar("清理Tag中...", assetBundleNames[i], process); AssetDatabase.RemoveAssetBundleName(assetBundleNames[i], true); } EditorUtility.ClearProgressBar(); } static string[] __GetBuildScenes() { List names = new List(); foreach (EditorBuildSettingsScene e in EditorBuildSettings.scenes) { if (e == null) continue; if (e.enabled) names.Add(e.path); } return names.ToArray(); } /// /// 判断目标是文件夹还是目录(目录包括磁盘) /// /// 文件名 /// static bool __IsDir(string filepath) { FileInfo fi = new FileInfo(filepath); if ((fi.Attributes & FileAttributes.Directory) != 0) return true; else { return false; } } class HashFile { public string hash; public string hash_path; public string path; public long fileSzie; public HashFile() { } public HashFile(string hash_path, string hash, string path) { this.hash_path = hash_path; this.hash = hash; this.path = path; } public override string ToString() { return hash_path + "|" + hash + "|" + path + "|" + (fileSzie / 1024) + "KB"; } } #region pack asset static void PackAsset_Effect(string dir, string type, string path, BuildTarget target, List ncList) { var tem_path = dir + path + "/effect"; var _cr_all_prefab = AssetDatabase.FindAssets("", new string[] { tem_path }); StringBuilder sb = new StringBuilder(); for (int i = 0; i < _cr_all_prefab.Length; i++) { var guid = _cr_all_prefab[i]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); if (__IsDir(assetPath)) { sb.Append(assetPath); string[] files = Directory.GetFiles(assetPath, "*.prefab", SearchOption.TopDirectoryOnly); assetPath = assetPath.Replace(dir, string.Empty); var packPath = assetPath.Replace('/', '$'); packPath = type + "/" + MD5Str(packPath); foreach (string str in files) { var tem_str = str.Replace('\\', '/'); sb.AppendLine(); sb.Append("--" + tem_str); AssetImporter ai = AssetImporter.GetAtPath(tem_str); ai.assetBundleName = packPath; FileInfo fi = new FileInfo(tem_str); tem_str = tem_str.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); var ac = new AssetConfig() { Name = name, Path = tem_str, PackPath = packPath }; ncList.Add(ac); } sb.AppendLine(); } } //UnityEngine.Debug.Log(StringBuilderCache.GetStringAndRelease(sb)); } static void PackAsset_UI(string dir, string type, string path, BuildTarget target, List ncList) { var tem_path = dir + path + "/ui"; var _cr_allui = AssetDatabase.FindAssets("_fui", new string[] { tem_path }); List _uipage_list = new List(); List _path_list = new List(); for (int j = 0; j < _cr_allui.Length; j++) { var guid = _cr_allui[j]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); FileInfo fi = new FileInfo(assetPath); if (fi.Extension != ".bytes") continue; assetPath = assetPath.Replace(fi.Name, string.Empty); _path_list.Add(assetPath); _uipage_list.Add(fi.Name.Replace("_fui.bytes", string.Empty)); } var fileCurNum = 0; var fileNum = _uipage_list.Count * 2; var i = 0; foreach (string str in _uipage_list) { var _cr_ui = AssetDatabase.FindAssets(str + "_", new string[] { tem_path }); i++; var packPath = (path + "/ui" + str).Replace('/', '$'); packPath = type + "/" + MD5Str(packPath); for (int j = 0; j < _cr_ui.Length; j++) { var guid = _cr_ui[j]; var assetPath = AssetDatabase.GUIDToAssetPath(guid); FileInfo fi = new FileInfo(assetPath); AssetImporter ai = AssetImporter.GetAtPath(assetPath); ai.assetBundleName = packPath; assetPath = assetPath.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); fileCurNum++; float process = ((float)fileCurNum) / (fileNum); EditorUtility.DisplayProgressBar(path + "->设置UI资源Tag中...", assetPath, process); AssetConfig ac = new AssetConfig() { Name = name, Path = assetPath, PackPath = packPath }; ncList.Add(ac); } } } static void PackAsset_BG(string dir, string type, string path, BuildTarget target, List ncList) { var tem_path = dir + path + "/bg"; var _cr_allbg = AssetDatabase.FindAssets("t:Texture", new string[] { tem_path }); var fileNum = _cr_allbg.Length; var fileCurNum = 0; for (int j = 0; j < _cr_allbg.Length; j++) { var guid = _cr_allbg[j]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); FileInfo fi = new FileInfo(assetPath); if (fi.Extension != ".png") continue; AssetImporter ai = AssetImporter.GetAtPath(assetPath); assetPath = assetPath.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); var packPath = assetPath.Replace(fi.Extension, string.Empty).Replace('/', '$'); packPath = type + "/" + MD5Str(packPath.ToLower()); ai.assetBundleName = packPath; fileCurNum++; float process = ((float)fileCurNum) / (fileNum); EditorUtility.DisplayProgressBar(path + "->设置背景Tag中...", assetPath, process); AssetConfig ac = new AssetConfig() { Name = name, Path = assetPath, PackPath = packPath }; ncList.Add(ac); } } static void PackAsset_Sound(string dir, string type, string path, BuildTarget target, List ncList) { var tem_path = dir + path + "/sound"; var _cr_allsound = AssetDatabase.FindAssets("t:AudioClip", new string[] { tem_path }); var fileNum = _cr_allsound.Length; var fileCurNum = 0; for (int j = 0; j < _cr_allsound.Length; j++) { var guid = _cr_allsound[j]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); FileInfo fi = new FileInfo(assetPath); AssetImporter ai = AssetImporter.GetAtPath(assetPath); assetPath = assetPath.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); var packPath = assetPath.Replace(fi.Extension, string.Empty).Replace('/', '$'); packPath = type + "/" + MD5Str(packPath); ai.assetBundleName = packPath; fileCurNum++; float process = ((float)fileCurNum) / (fileNum); EditorUtility.DisplayProgressBar("设置声音Tag中...", assetPath, process); AssetConfig ac = new AssetConfig() { Name = name, Path = assetPath, PackPath = packPath }; ncList.Add(ac); } } static void PackAsset_Curve(string dir, string type, string path, BuildTarget target, List ncList) { var tem_path = dir + path + "/curve"; var _cr_allcurve = AssetDatabase.FindAssets("t", new string[] { tem_path }); var _curve_pack = type + "/" + MD5Str("curve$data"); for (int j = 0; j < _cr_allcurve.Length; j++) { var guid = _cr_allcurve[j]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); FileInfo fi = new FileInfo(assetPath); if (fi.Extension != ".asset") continue; AssetImporter ai = AssetImporter.GetAtPath(assetPath); ai.assetBundleName = _curve_pack; assetPath = assetPath.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); AssetConfig ac = new AssetConfig() { Name = name, Path = assetPath, PackPath = _curve_pack }; ncList.Add(ac); } } static void PackAsset_Font(string dir, string type, string path, BuildTarget target, List ncList) { var tem_path = dir + path + "/fonts"; var _cr_allfont = AssetDatabase.FindAssets("t:Font", new string[] { tem_path }); var fileNum = _cr_allfont.Length; var fileCurNum = 0; for (int j = 0; j < _cr_allfont.Length; j++) { var guid = _cr_allfont[j]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); FileInfo fi = new FileInfo(assetPath); AssetImporter ai = AssetImporter.GetAtPath(assetPath); assetPath = assetPath.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); var packPath = assetPath.Replace(fi.Extension, string.Empty).Replace('/', '$'); packPath = type + "/" + MD5Str(packPath); ai.assetBundleName = packPath; fileCurNum++; float process = ((float)fileCurNum) / (fileNum); EditorUtility.DisplayProgressBar("设置字体Tag中...", assetPath, process); AssetConfig ac = new AssetConfig() { Name = name, Path = assetPath, PackPath = packPath }; ncList.Add(ac); } } static void PackAsset_Prefab(string dir, string type, string path, BuildTarget target, List ncList) { // 构建完整的预制体资源目录路径 var temp_path = dir + path; UnityEngine.Debug.Log("执行预制体打包流程: " + temp_path); var _cr_allprefab = AssetDatabase.FindAssets("t:GameObject", new string[] { temp_path }); var fileNum = _cr_allprefab.Length; var fileCurNum = 0; // 用于记录已处理的资源,避免重复 HashSet processedAssets = new HashSet(); for (int j = 0; j < _cr_allprefab.Length; j++) { var guid = _cr_allprefab[j]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); // 检查文件扩展名,确保是.prefab文件 if (!assetPath.EndsWith(".prefab", System.StringComparison.OrdinalIgnoreCase)) continue; // 跳过已处理的资源 if (processedAssets.Contains(assetPath)) continue; FileInfo fi = new FileInfo(assetPath); AssetImporter ai = AssetImporter.GetAtPath(assetPath); // 处理路径:移除基础目录,获取相对路径 string relativePath = assetPath.Replace(dir, string.Empty); var name = fi.Name.Replace(fi.Extension, string.Empty); // 生成打包路径:替换斜杠为$,添加类型前缀,并进行MD5加密 var packPath = relativePath.Replace(fi.Extension, string.Empty).Replace('/', '$'); packPath = type + "/" + MD5Str(packPath); // 🔧 核心修复:收集并设置所有依赖资源的 AssetBundle ProcessPrefabWithDependencies(assetPath, packPath, processedAssets); // 更新进度 fileCurNum++; float process = ((float)fileCurNum) / fileNum; EditorUtility.DisplayProgressBar("设置预制体AssetBundle中...", $"{name} - 包含依赖资源", process); // 创建资源配置对象并添加到列表 AssetConfig ac = new AssetConfig() { Name = name, Path = relativePath, PackPath = packPath }; ncList.Add(ac); UnityEngine.Debug.Log($"预制体: {name}, AssetBundle: {packPath}"); } EditorUtility.ClearProgressBar(); } static void ProcessPrefabWithDependencies(string prefabPath, string bundleName, HashSet processedAssets) { // 获取预制体的所有直接依赖 string[] dependencies = AssetDatabase.GetDependencies(prefabPath, true); //UnityEngine.Debug.Log($"处理预制体: {prefabPath}"); //UnityEngine.Debug.Log($"依赖资源数量: {dependencies.Length}"); foreach (string dependency in dependencies) { // 跳过自己 if (dependency == prefabPath) continue; // 跳过脚本文件 if (dependency.EndsWith(".cs")) continue; // 跳过已处理的资源 if (processedAssets.Contains(dependency)) continue; // 设置依赖资源的 AssetBundle AssetImporter dependencyImporter = AssetImporter.GetAtPath(dependency); if (dependencyImporter != null) { dependencyImporter.assetBundleName = bundleName; processedAssets.Add(dependency); } } // 最后设置预制体本身的 AssetBundle AssetImporter prefabImporter = AssetImporter.GetAtPath(prefabPath); if (prefabImporter != null) { prefabImporter.assetBundleName = bundleName; processedAssets.Add(prefabPath); } } static void PackAsset_All_Res(string type, string path, BuildTarget target, List ncList) { PackAsset_All(RES_DIR, type, path, target, ncList); } static void PackAsset_All(string type, string path, BuildTarget target, List ncList) { PackAsset_All(ART_DIR, type, path, target, ncList); } static void PackAsset_All(string dir, string type, string path, BuildTarget target, List ncList) { PackAsset_Effect(dir, type, path, target, ncList); PackAsset_UI(dir, type, path, target, ncList); PackAsset_BG(dir, type, path, target, ncList); PackAsset_Sound(dir, type, path, target, ncList); PackAsset_Curve(dir, type, path, target, ncList); PackAsset_Font(dir, type, path, target, ncList); PackAsset_Prefab(dir, type, path, target, ncList); } static string WriteAssetConfig(List ncList, string pack_path, string type, Dictionary filehash) { var array = new ByteArray(); array.writeInt(ncList.Count); foreach (AssetConfig config in ncList) { array.writeString(config.Name); array.writeString(config.Path); array.writeString(config.PackPath); if (filehash != null && !filehash.ContainsKey(config.PackPath)) { HashFile hf = new HashFile(config.PackPath, MD5file(pack_path + "/" + config.PackPath), config.Path); FileInfo fileInfo = new FileInfo(pack_path + "/" + config.PackPath); hf.fileSzie = fileInfo.Length; filehash.Add(config.PackPath, hf); } } var dir = pack_path + "/" + type + "/"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } //写入资源配置 var config_pack = dir + "asset_config.bytes"; UnityEngine.Debug.Log("资源配置:"+config_pack); File.WriteAllBytes(config_pack, array.bytes); return config_pack; } #endregion static bool isBuild = false; public static void PackAsset(BuildTarget target, bool pack_test, ArrayList config_list = null) { if (!isBuild && EditorApplication.isCompiling) { EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定"); return; } isBuild = true; EditorUserBuildSettings.SwitchActiveBuildTarget(target); AssetDatabase.Refresh(); __ClearAllAssetNames(); AssetDatabase.Refresh(); if (config_list == null) { return; } string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + "Pack/"; for (int i = 0; i < config_list.Count; ++i) { var tem = (Hashtable)config_list[i]; if (tem.ContainsKey("is_pack") && !(bool)tem["is_pack"]) continue; var ver = tem["ver"]; var is_res = tem.ContainsKey("is_res") ? (bool)tem["is_res"] : false; var p_name = (string)tem["name"]; UnityEngine.Debug.Log("base_name:" + p_name); var asset_path = "base/" + p_name; string tempdir = ResourcesManager.OS_Dir; if (BuildBaseWindow.build32Lua) { tempdir = tempdir + "32"; } var version_path = string.Format("{0}/{1}/{2}/", fileName, tempdir, asset_path); if (!Directory.Exists(version_path)) { Directory.CreateDirectory(version_path); } //setp 1 创建资源包临时目录 var pack_path = fileName + "temp"; if (Directory.Exists(pack_path + "/")) { Directory.Delete(pack_path + "/", true); } Directory.CreateDirectory(pack_path + "/"); //setp 2 设置bundles配置 var ncList = new List(); if (is_res) { PackAsset_All_Res(asset_path, asset_path, target, ncList); } else { PackAsset_All(asset_path, asset_path, target, ncList); } if (ncList.Count > 0) { var option = BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.DeterministicAssetBundle | BuildAssetBundleOptions.DisableWriteTypeTree; BuildPipeline.BuildAssetBundles(pack_path, option, target); //setp 3 生成MD5码 EditorUtility.DisplayProgressBar("", "正在生成MD5码", 0.5f); //var filehash = new Dictionary(); var config_pack = WriteAssetConfig(ncList, pack_path, asset_path, null); } //setp 4 打包lua脚本 bool lua = false; var tem_str = (string)tem["lua_path"]; if (!string.IsNullOrEmpty(tem_str)) { var lua_paths = new List(); var tem_arr = tem_str.Split(','); foreach (string str in tem_arr) { lua_paths.Add(LuaConst.luaDir + str); } LuaBuildUtil.BuildLuaBundles(pack_path, lua_paths); lua = lua_paths.Count > 0; //filehash.Add("lua_pack", new HashFile("lua_pack", MD5file(pack_path + "/lua_pack"), "lua_pack")); } EditorUtility.DisplayProgressBar("", "正在压缩打包资源", 0.5f); //setp 5 打包资源,无压缩 if (lua || ncList.Count > 0) { var file_name = string.Format("asset_pack{0}.bytes", (string)tem["ver"]); var file = version_path + file_name; CreateAssetPack(pack_path, file); // #if UNITY_IPHONE // if (tem.ContainsKey("check")&& (bool)tem["check"]) // { // CopyStreamPath(file, asset_path,file_name); // } // #endif if (!string.IsNullOrEmpty(HOT_BASE_PATH)) { string tempdir1 = ResourcesManager.OS_Dir; if (BuildBaseWindow.build32Lua) { tempdir1 = tempdir1 + "32"; } var tem_path = string.Format("{0}/{1}/{2}/{3}", HOT_BASE_PATH, tempdir1, asset_path, file_name); var dir = Path.GetDirectoryName(tem_path); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (File.Exists(tem_path)) File.Delete(tem_path); File.Copy(file, tem_path); } } else { Directory.Delete(version_path, true); } Directory.Delete(pack_path + "/", true); __ClearAllAssetNames(); } AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssetsImmediate(); System.GC.Collect(); isBuild = false; } public static void PackAsset_Extend(BuildTarget target, bool pack_test, ArrayList config_list = null) { if (!isBuild && EditorApplication.isCompiling) { EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定"); return; } isBuild = true; EditorUserBuildSettings.SwitchActiveBuildTarget(target); AssetDatabase.Refresh(); __ClearAllAssetNames(); if (config_list == null) { return; } string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + "Pack"; for (int i = 0; i < config_list.Count; ++i) { var tem = (Hashtable)config_list[i]; if (tem.ContainsKey("is_pack") && !(bool)tem["is_pack"]) continue; UnityEngine.Debug.Log("id:" + tem["game_id"] + "name:" + tem["name"]); var asset_path = (string)tem["bundle"]; asset_path = asset_path.Replace('.', '/'); string tempdir = ResourcesManager.OS_Dir; if (BuildBaseWindow.build32Lua) { tempdir = tempdir + "32"; } var version_path = string.Format("{0}/{1}/{2}/", fileName, tempdir, asset_path); if (!Directory.Exists(version_path)) { Directory.CreateDirectory(version_path); } //setp 3 创建资源包临时目录 var pack_path = fileName + "/temp"; if (Directory.Exists(pack_path + "/")) { Directory.Delete(pack_path + "/", true); } Directory.CreateDirectory(pack_path + "/"); var ncList = new List(); PackAsset_All(asset_path, asset_path, target, ncList); var option = BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.DeterministicAssetBundle | BuildAssetBundleOptions.DisableWriteTypeTree; BuildPipeline.BuildAssetBundles(pack_path, option, target); //正在生成MD5码 EditorUtility.DisplayProgressBar((string)tem["name"], "正在生成MD5码", 0.5f); var config_pack = WriteAssetConfig(ncList, pack_path, asset_path, null); var lua_dir = LuaConst.luaDir + "/extend_project/" + asset_path; if (!string.IsNullOrEmpty(lua_dir)) { //打包lua脚本 LuaBuildUtil.BuildLuaBundles(pack_path, new List() { lua_dir }, asset_path); } var file_name = string.Format("asset_pack{0}.bytes", (string)tem["version"]); var file = version_path + file_name; CreateAssetPack(pack_path, file); Directory.Delete(pack_path + "/", true); if (!string.IsNullOrEmpty(HOT_EXTEND_PATH)) { var tem_path = string.Format("{0}/{1}/{2}/{3}", HOT_EXTEND_PATH, ResourcesManager.OS_Dir, asset_path, file_name); var dir = Path.GetDirectoryName(tem_path); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (File.Exists(tem_path)) File.Delete(tem_path); File.Copy(file, tem_path); } __ClearAllAssetNames(); } AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); EditorUtility.UnloadUnusedAssetsImmediate(); System.GC.Collect(); isBuild = false; } public static void DeleteFilesAndFoldersRecursively(string target_dir) { foreach (string file in Directory.GetFiles(target_dir)) { File.Delete(file); } foreach (string subDir in Directory.GetDirectories(target_dir)) { DeleteFilesAndFoldersRecursively(subDir); } Thread.Sleep(1); // This makes the difference between whether it works or not. Sleep(0) is not enough. Directory.Delete(target_dir); } static MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); /// /// 计算文件的MD5值 /// static string MD5file(string file) { try { FileStream fs = new FileStream(file, FileMode.Open); byte[] retVal = md5.ComputeHash(fs); fs.Close(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } catch (Exception ex) { throw new Exception("md5file() fail, error:" + ex.Message); } } static string MD5Str(string msg) { try { System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(msg); byte[] hash = md5.ComputeHash(inputBytes); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hash.Length; i++) { sb.Append(hash[i].ToString("x2")); } return sb.ToString(); } catch (Exception ex) { throw new Exception("md5str() fail, error:" + ex.Message); } } static void CreateAssetPack(string dir, string filename) { IFilePack zf = null; zf = new FilePack20(filename, PackMode.Write); zf.PackFile(dir, ".meta|.manifest"); zf = null; } static void CopyStreamPath(string src_file, string base_path, string file_name) { var sap = Application.streamingAssetsPath + string.Format("/{0}/{1}", ResourcesManager.OS_Dir, base_path); if (!Directory.Exists(sap)) { Directory.CreateDirectory(sap); } var pack_path = sap + "/" + file_name; if (File.Exists(pack_path)) File.Delete(pack_path); File.Copy(src_file, pack_path); } static bool SetScriptingDefineSymbolsForGroup(BuildTargetGroup target, string symbolsForGroup) { PlayerSettings.SetScriptingDefineSymbolsForGroup(target, symbolsForGroup); return true; } public static void BuildForAndroid_Test() { PlayerSettings.Android.keystoreName = Application.dataPath + "/../debug.keystore"; PlayerSettings.Android.keystorePass = "android"; PlayerSettings.keyaliasPass = "androiddebugkey"; PlayerSettings.keyaliasPass = "android"; } [MenuItem("BuildTools/Opt-App(Pro)")] static void BuildForApp_Pro() { if (!isBuild && EditorApplication.isCompiling) { EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定"); return; } BuildTargetGroup target = BuildTargetGroup.Standalone; #if UNITY_IPHONE target = BuildTargetGroup.iOS; #elif UNITY_ANDROID target = BuildTargetGroup.Android; #endif isBuild = SetScriptingDefineSymbolsForGroup(target, "FAIRYGUI_TOLUA;Build_App;NOT_ACCOUT_TEST;NOT_HOUSE_TEST"); #if UNITY_ANDROID BuildForAndroid_Test(); #endif UnityEngine.Debug.Log("set pro..."); isBuild = false; } [MenuItem("BuildTools/Opt-App(Test)")] static void BuildForApp_Test() { if (!isBuild && EditorApplication.isCompiling) { EditorUtility.DisplayDialog("警告", "请等待编辑器完成编译再执行此功能", "确定"); return; } BuildTargetGroup target = BuildTargetGroup.Standalone; #if UNITY_IPHONE target = BuildTargetGroup.iOS; #elif UNITY_ANDROID target = BuildTargetGroup.Android; #endif isBuild = SetScriptingDefineSymbolsForGroup(target, "FAIRYGUI_TOLUA;Build_App;NOT_ACCOUT_TEST;NOT_HOUSE_TEST;INIT_JSON_TEST"); #if UNITY_ANDROID BuildForAndroid_Test(); #endif UnityEngine.Debug.Log("set test..."); isBuild = false; } static BuildTarget GetBuildTarget() { BuildTarget target = BuildTarget.StandaloneWindows64; #if UNITY_IPHONE target = BuildTarget.iOS; #elif UNITY_ANDROID target = BuildTarget.Android; #endif return target; } public static void Specify_Pack_Custom(BuildTarget target, ArrayList config_list) { PackAsset_Extend(target, true, config_list); } public static void Base_Pack_Custom(BuildTarget target, ArrayList config_list) { PackAsset(target, true, config_list); } }