From d41b4c227f5af7dc0d4d74f4957d95700393f495 Mon Sep 17 00:00:00 2001 From: zhouzhuo Date: Tue, 5 Aug 2025 14:55:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8=E7=94=9F?= =?UTF-8?q?=E6=88=90=E8=BE=B9=E6=A1=86=E9=A2=84=E5=88=B6=E4=BD=93=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Editor/BuildBundlesHelper.cs | 162 ++++++++++++++++++ pipeline_Profile/code_file/build_profile.py | 110 ++++++++---- 2 files changed, 235 insertions(+), 37 deletions(-) diff --git a/pipeline_Profile/build_profile_package/Assets/Editor/BuildBundlesHelper.cs b/pipeline_Profile/build_profile_package/Assets/Editor/BuildBundlesHelper.cs index a9358e8..4b26380 100644 --- a/pipeline_Profile/build_profile_package/Assets/Editor/BuildBundlesHelper.cs +++ b/pipeline_Profile/build_profile_package/Assets/Editor/BuildBundlesHelper.cs @@ -42,6 +42,9 @@ public static class BuildBundlesHelper [MenuItem("Tools/TestBuildBundles")] public static void TestBuildBundles() { + Debug.LogWarning("MakePrefabs Start =================="); + MakePrefabs(); + Debug.LogWarning("MakePrefabs End =================="); Debug.LogWarning("MakeAtlas Start =================="); MakeAtlas(); AssetDatabase.Refresh(); @@ -83,6 +86,9 @@ public static class BuildBundlesHelper public static void BuildBundles() { + Debug.LogWarning("MakePrefabs Start =================="); + MakePrefabs(); + Debug.LogWarning("MakePrefabs End =================="); Debug.LogWarning("MakeAtlas Start =================="); MakeAtlas(); AssetDatabase.Refresh(); @@ -134,6 +140,162 @@ public static class BuildBundlesHelper Debug.LogWarning("BuildBundles End ==================> exe"); } + #region 创建边框预制体 + + [MenuItem("Tools/MakePrefabs")] + public static void MakePrefabsMenuItem() + { + MakePrefabs(); + } + + /// + /// 根据指定文件夹中的PNG图片生成预制体 + /// + /// 包含PNG图片的文件夹路径 + public static void MakePrefabs(string dir = "Assets/AssetRaw/UIRaw/frame_image") + { + if (!AssetDatabase.IsValidFolder(dir)) + { + Debug.LogError($"不存在的目录:{dir}"); + return; + } + + // 获取文件夹中所有PNG图片 + string[] allPics = Directory.GetFiles(dir, "*.png", SearchOption.TopDirectoryOnly); + if (allPics.Length == 0) + { + Debug.LogError($"目录中没有找到PNG图片:{dir}"); + return; + } + + // 创建预制体保存目录 + string prefabDir = dir.Replace("frame_image", "frame_prefabs"); + if (!AssetDatabase.IsValidFolder(prefabDir)) + { + Directory.CreateDirectory(prefabDir); + AssetDatabase.Refresh(); + } + + int successCount = 0; + foreach (var picPath in allPics) + { + if (picPath.EndsWith(".meta")) + continue; + + // 转换为Unity资源路径 + string assetPath = picPath.Replace("\\", "/"); + + // 加载Sprite资源 + Sprite sprite = AssetDatabase.LoadAssetAtPath(assetPath); + if (sprite == null) + { + Debug.LogWarning($"无法加载Sprite: {assetPath}"); + continue; + } + + // 从文件名提取数字部分作为预制体名称 + string fileName = Path.GetFileNameWithoutExtension(assetPath); + string prefabName = ExtractNumberFromFileName(fileName); + + if (string.IsNullOrEmpty(prefabName)) + { + Debug.LogWarning($"无法从文件名提取数字: {fileName}"); + continue; + } + + // 创建预制体 + if (CreateFramePrefab(sprite, prefabName, prefabDir)) + { + successCount++; + Debug.Log($"成功创建预制体: {prefabName}"); + } + } + + AssetDatabase.Refresh(); + Debug.Log($"预制体创建完成,成功创建 {successCount} 个预制体"); + } + + /// + /// 从文件名中提取数字部分 + /// + /// 文件名,如 "frame_2000" + /// 提取的数字字符串,如 "2000" + private static string ExtractNumberFromFileName(string fileName) + { + // 查找最后一个下划线的位置 + int lastUnderscoreIndex = fileName.LastIndexOf('_'); + if (lastUnderscoreIndex >= 0 && lastUnderscoreIndex < fileName.Length - 1) + { + string numberPart = fileName.Substring(lastUnderscoreIndex + 1); + // 验证是否为纯数字 + if (System.Text.RegularExpressions.Regex.IsMatch(numberPart, @"^\d+$")) + { + return numberPart; + } + } + + // 如果没有找到下划线,尝试提取文件名中的所有数字 + var match = System.Text.RegularExpressions.Regex.Match(fileName, @"\d+"); + if (match.Success) + { + return match.Value; + } + + return null; + } + + /// + /// 创建包含Image组件的预制体 + /// + /// 要使用的Sprite + /// 预制体名称 + /// 预制体保存目录 + /// 是否创建成功 + private static bool CreateFramePrefab(Sprite sprite, string prefabName, string prefabDir) + { + try + { + // 创建空的GameObject + GameObject frameObject = new GameObject(prefabName); + + // 添加RectTransform组件(UI元素必需) + RectTransform rectTransform = frameObject.AddComponent(); + + // 添加Image组件 + UnityEngine.UI.Image imageComponent = frameObject.AddComponent(); + imageComponent.sprite = sprite; + imageComponent.preserveAspect = true; + + // 设置RectTransform的大小为图片的实际像素大小 + rectTransform.sizeDelta = new Vector2(sprite.rect.width, sprite.rect.height); + // 设置为中心对齐 + rectTransform.anchorMin = new Vector2(0.5f, 0.5f); + rectTransform.anchorMax = new Vector2(0.5f, 0.5f); + rectTransform.pivot = new Vector2(0.5f, 0.5f); + rectTransform.anchoredPosition = Vector2.zero; + + // 确保Image组件不会改变原始图片尺寸 + imageComponent.type = UnityEngine.UI.Image.Type.Simple; + imageComponent.preserveAspect = false; // 改为false,严格按照sizeDelta设置的尺寸显示 + + // 保存为预制体 + string prefabPath = $"{prefabDir}/{prefabName}.prefab"; + GameObject prefab = PrefabUtility.SaveAsPrefabAsset(frameObject, prefabPath); + + // 清理临时GameObject + Object.DestroyImmediate(frameObject); + + return prefab != null; + } + catch (System.Exception e) + { + Debug.LogError($"创建预制体失败 {prefabName}: {e.Message}"); + return false; + } + } + + #endregion + #region 创建图集 private static void MakeAtlas() diff --git a/pipeline_Profile/code_file/build_profile.py b/pipeline_Profile/code_file/build_profile.py index 28c2917..4d305d9 100644 --- a/pipeline_Profile/code_file/build_profile.py +++ b/pipeline_Profile/code_file/build_profile.py @@ -29,7 +29,7 @@ sys.path.insert(0, os.path.join(tools_path, "config_convert")) sys.path.insert(0, os.path.join(tools_path, "build_package")) platform = "Android" -env = "release" +env = "Release" if len(sys.argv) > 1: platform = sys.argv[1] if len(sys.argv) > 1: @@ -264,26 +264,61 @@ def get_type_value(field_type, value): def copy_file_to_unity(): ''' 软链接资源到unity里面 ''' + uiraw_path = os.path.join(PROJECT_PATH, "Assets/AssetRaw/UIRaw/") + + # 确保目录存在 + utils.mkdirs(uiraw_path) + + # 删除现有的符号链接和文件 try: - for root, dirs, files in os.walk(os.path.join(PROJECT_PATH, "Assets/AssetRaw/UIRaw/")): - for dir in dirs: - os.unlink(os.path.join(root, dir)) - for root, dirs, files in os.walk(os.path.join(PROJECT_PATH, "Assets/AssetRaw/UIRaw/")): - for file in files: - os.remove(os.path.join(root, file)) + if os.path.exists(uiraw_path): + # 删除目录中的所有内容 + for item in os.listdir(uiraw_path): + item_path = os.path.join(uiraw_path, item) + if os.path.islink(item_path): + # 如果是符号链接,直接删除 + os.unlink(item_path) + elif os.path.isfile(item_path): + # 如果是普通文件,删除 + os.remove(item_path) + elif os.path.isdir(item_path): + # 如果是目录,递归删除 + shutil.rmtree(item_path) except Exception as e: - print(e) + print(f"清理现有文件时出错: {e}") + # 创建新的符号链接 utils.mkdirs(os.path.dirname(ASSET_PATH)) for root, dirs, files in os.walk(ASSET_PATH): for dir in dirs: - os.symlink(os.path.join(root, dir), os.path.join(PROJECT_PATH, f"Assets/AssetRaw/UIRaw/{dir}")) + source_path = os.path.join(root, dir) + target_path = os.path.join(PROJECT_PATH, f"Assets/AssetRaw/UIRaw/{dir}") + + # 确保目标路径不存在 + if os.path.exists(target_path) or os.path.islink(target_path): + if os.path.islink(target_path): + os.unlink(target_path) + elif os.path.isdir(target_path): + shutil.rmtree(target_path) + else: + os.remove(target_path) + + os.symlink(source_path, target_path) + # 处理JSON文件 + json_target_path = os.path.join(PROJECT_PATH, f"Assets/AssetRaw/UIRaw/profile.json") + if os.path.exists(json_target_path) or os.path.islink(json_target_path): + if os.path.islink(json_target_path): + os.unlink(json_target_path) + else: + os.remove(json_target_path) + if os.path.exists(json_path): - os.symlink(json_path, os.path.join(PROJECT_PATH, f"Assets/AssetRaw/UIRaw/profile.json")) + os.symlink(json_path, json_target_path) else: print("json文件不存在,有问题") raise Exception("json文件不存在,有问题") + print("软链接拷贝成功") @@ -337,33 +372,32 @@ def upload_package(is_build_success, ab_dir): ''' 上传资源包到storage ''' print(f"ab_path {ab_dir}") if is_build_success: - print(f"开始上传ab包到firebase") - storage_path = "Bundles/{}".format(platform) + f'/Profile/profile-{env}.bundle' - - # 从ab_dir文件夹下获取所有.bundle文件 - bundle_file = "" - if os.path.exists(ab_dir): - for root, dirs, files in os.walk(ab_dir): - for file in files: - if file.endswith('.bundle'): - bundle_file_path = os.path.join(root, file) - bundle_file = bundle_file_path - print(f"找到bundle文件: {bundle_file_path}") - break - - if bundle_file == "": - print(f"没有找到资源包") - raise Exception("没有找到资源包") + print(f"开始上传资源包到firebase") + # storage_path = "Bundles/{}".format(platform) + f'/Profile/profile-{env}.bundle' + # # 从ab_dir文件夹下获取所有.bundle文件 + # bundle_file = "" + # if os.path.exists(ab_dir): + # for root, dirs, files in os.walk(ab_dir): + # for file in files: + # if file.endswith('.bundle'): + # bundle_file_path = os.path.join(root, file) + # bundle_file = bundle_file_path + # print(f"找到bundle文件: {bundle_file_path}") + # break + # + # if bundle_file == "": + # print(f"没有找到资源包") + # raise Exception("没有找到资源包") + storage_path = "Bundles/{}".format(platform) + f'/ProfilesFeature/{env}' tmUploadPackage1 = time.time() - generation = helper.upload_file(storage_path, bundle_file) - # upload_firebase_storage.upload_directory(helper,storage_path,ab_dir, ".version") + # generation = helper.upload_file(storage_path, bundle_file) + upload_firebase_storage.upload_directory(helper, storage_path, ab_dir, ".version") tmUploadPackage2 = time.time() print(f"firebase上传耗时:{tmUploadPackage2 - tmUploadPackage1}") - return generation, storage_path -def refresh_remote_config(url): +def refresh_remote_config(time_stamp): ''' 刷新云控 ''' remote_key = "profile_asset_config" # with open(REMOTE_CONFIG_FILE, "r") as f: @@ -376,12 +410,16 @@ def refresh_remote_config(url): # value_json = json.loads(value) # value_json[env] = url - helper.update_remote_config(None, None, remote_key, env, url) + helper.update_remote_config(None, None, remote_key, env, time_stamp) + +def get_time_stamp(): + """返回当前时间的时间戳""" + return int(time.time()) if __name__ == "__main__": # platform = "Android" - # env = 'debug' + # env = 'Debug' print(1) helper = FirebaseHelper() get_json() @@ -391,9 +429,7 @@ if __name__ == "__main__": tmBuildPackage2 = time.time() print(f" unity打包耗时:{tmBuildPackage2 - tmBuildPackage1}") time.sleep(1) - generation, storage_path = upload_package(is_build_success, ab_dir) - url = f"{config.cdn}/{storage_path}?generation={generation}" - print(url) + upload_package(is_build_success, ab_dir) time.sleep(1) - refresh_remote_config(url) + refresh_remote_config(get_time_stamp()) print(2)