三国卡牌客户端基础资源仓库
hch
2026-09-25 51497d37d2ea18aa4e439250119bb6f01224f519
0312 修复图集死循环问题
3个文件已修改
140 ■■■■■ 已修改文件
Assets/Editor/Tool/TexturePlatformAssetPostprocessor.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Tool/TexturePlatformFormatHelper.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Tool/UpdateSpritePackingSetting.cs 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Tool/TexturePlatformAssetPostprocessor.cs
@@ -15,6 +15,11 @@
    private static readonly string TARGET_FOLDER = TexturePlatformFormatHelper.TARGET_FOLDER;
    private static readonly bool AUTO_APPLY_ATLAS_SETTINGS = true;
    /// <summary>
    /// 防止回调中 SaveAndReimport 同步触发下一次 OnPostprocessAllAssets 造成嵌套重入。
    /// </summary>
    private static bool s_IsApplying;
    void OnPreprocessTexture()
    {
        if (!assetPath.StartsWith(TARGET_FOLDER))
@@ -38,30 +43,41 @@
    {
        if (!AUTO_APPLY_ATLAS_SETTINGS)
            return;
        // 回调里的 SaveAndReimport 会同步再次触发本回调,必须挡掉,否则会无限自触发
        if (s_IsApplying)
            return;
        foreach (var assetPath in importedAssets)
        s_IsApplying = true;
        try
        {
            if (!assetPath.StartsWith(TARGET_FOLDER))
                continue;
            if (!assetPath.EndsWith(".spriteatlasv2") && !assetPath.EndsWith(".spriteatlas"))
                continue;
            try
            foreach (var assetPath in importedAssets)
            {
                var importer = SpriteAtlasImporter.GetAtPath(assetPath) as SpriteAtlasImporter;
                if (importer == null)
                if (!assetPath.StartsWith(TARGET_FOLDER))
                    continue;
                if (!assetPath.EndsWith(".spriteatlasv2") && !assetPath.EndsWith(".spriteatlas"))
                    continue;
                if (TexturePlatformFormatHelper.ApplyAtlasPlatformSettings(importer))
                try
                {
                    importer.SaveAndReimport();
                    Debug.Log($"[TexImport] 图集: {assetPath}");
                    var importer = SpriteAtlasImporter.GetAtPath(assetPath) as SpriteAtlasImporter;
                    if (importer == null)
                        continue;
                    if (TexturePlatformFormatHelper.ApplyAtlasPlatformSettings(importer))
                    {
                        importer.SaveAndReimport();
                        Debug.Log($"[TexImport] 图集: {assetPath}");
                    }
                }
                catch (System.Exception ex)
                {
                    Debug.LogError($"[TexImport] 图集失败 {assetPath}: {ex.Message}");
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError($"[TexImport] 图集失败 {assetPath}: {ex.Message}");
            }
        }
        finally
        {
            s_IsApplying = false;
        }
    }
}
Assets/Editor/Tool/TexturePlatformFormatHelper.cs
@@ -142,15 +142,28 @@
        return changed;
    }
    /// <summary>
    /// 会被真正写入 meta 的图集平台(只有 overridden=true 的平台设置才会被持久化)。
    /// Standalone / DefaultTexturePlatform 按需求保持默认,不做覆盖。
    /// </summary>
    public static readonly string[] OVERRIDDEN_ATLAS_PLATFORMS = { "Android", "iPhone", "WebGL" };
    /// <summary>
    /// 统一图集平台的 maxTextureSize。
    /// 注意:绝不能对 overridden=false 的平台写 maxTextureSize —— 这类设置不会被持久化,
    /// 每次导入读回来仍是默认值,会被判成"有改动"从而在 OnPostprocessAllAssets 里反复
    /// SaveAndReimport,最终触发 Unity 的 "infinite import loop" 检测。
    /// </summary>
    public static bool ApplyAtlasMaxTextureSize(SpriteAtlasImporter importer)
    {
        bool changed = false;
        foreach (var platform in new[] { "Standalone", "Android", "iPhone", "WebGL", "DefaultTexturePlatform" })
        foreach (var platform in OVERRIDDEN_ATLAS_PLATFORMS)
        {
            var settings = importer.GetPlatformSettings(platform);
            if (settings.maxTextureSize == ATLAS_MAX_SIZE)
            if (settings.overridden && settings.maxTextureSize == ATLAS_MAX_SIZE)
                continue;
            settings.overridden = true;
            settings.maxTextureSize = ATLAS_MAX_SIZE;
            importer.SetPlatformSettings(settings);
            changed = true;
Assets/Editor/Tool/UpdateSpritePackingSetting.cs
@@ -13,8 +13,34 @@
    static string rootPath = Application.dataPath + "/ResourcesOut/Sprite";
    static string spriteRelativePath = "Assets/ResourcesOut/Sprite";
    /// <summary>
    /// 图集处理流程的重入保护:流程内部会大量 SaveAndReimport / ImportAsset,
    /// 这些都会触发 AssetPostprocessor,若不挡住重入就会与批处理/菜单触发形成互相导入。
    /// </summary>
    private static bool s_IsRunning;
    [MenuItem("程序/Sprite/标准化Sprite设置")]
    public static void UpdateAllSpritePackingSetting()
    {
        if (s_IsRunning)
        {
            Debug.LogWarning("[SpritePack] 上一次图集处理尚未结束,已跳过本次调用");
            return;
        }
        s_IsRunning = true;
        try
        {
            UpdateAllSpritePackingSettingInternal();
        }
        finally
        {
            s_IsRunning = false;
            EditorUtility.ClearProgressBar();
        }
    }
    private static void UpdateAllSpritePackingSettingInternal()
    {
        var path = "Assets/Editor/SpritePacking/SpriteSettings.asset";
        var so = AssetDatabase.LoadAssetAtPath<SpriteSettingConfig>(path);
@@ -107,7 +133,7 @@
        EditorUtility.ClearProgressBar();
        SpritePack();
        SpritePackInternal();
    }
    [MenuItem("程序/Sprite/打包BuiltIn图集")]
@@ -151,6 +177,11 @@
                }
            };
            spriteAtlas = CreateSpriteAtlas(spriteRelativePath_BuiltIn, setting);
            if (spriteAtlas == null)
            {
                Debug.LogError($"[SpritePack] 创建 BuiltIn 图集失败: {builtInSpritePath}");
                return;
            }
        }
        List<string> excludePngs = new List<string>() { "Launch_1.png", "Launch_2.png", "Launch_3.png", "LoginBackGround.png", "TB_DL_Logo.png" };
@@ -166,6 +197,26 @@
    [MenuItem("程序/Sprite/打包图集")]
    public static void SpritePack()
    {
        if (s_IsRunning)
        {
            Debug.LogWarning("[SpritePack] 上一次图集处理尚未结束,已跳过本次调用");
            return;
        }
        s_IsRunning = true;
        try
        {
            SpritePackInternal();
        }
        finally
        {
            s_IsRunning = false;
            EditorUtility.ClearProgressBar();
        }
    }
    private static void SpritePackInternal()
    {
        var path = "Assets/Editor/SpritePacking/SpriteSettings.asset";
        var so = AssetDatabase.LoadAssetAtPath<SpriteSettingConfig>(path);
@@ -195,6 +246,11 @@
            if (spriteAtlas == null)
            {
                spriteAtlas = CreateSpriteAtlas(spriteRelativePath, setting);
                if (spriteAtlas == null)
                {
                    Debug.LogError($"[SpritePack] 创建图集失败: {filePath}");
                    continue;
                }
            }
            string spriteFilePath = rootPath + "/" + spritefilePathName;
@@ -233,8 +289,12 @@
        string atlasPath = outPath + "/" + setting.folderName + ".spriteatlasv2";
        CreateEmptySpriteAtlas(atlasPath);
        SpriteAtlasImporter atlasImporter = SpriteAtlasImporter.GetAtPath(atlasPath) as SpriteAtlasImporter;
        if (atlasImporter == null)
        {
            Debug.LogError($"[SpritePack] 获取 SpriteAtlasImporter 失败: {atlasPath}");
            return null;
        }
        #region 图集基础设置
@@ -288,7 +348,11 @@
    {
        SpriteAtlasAsset.Save(new SpriteAtlasAsset(), atlasPath);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        // 这里只能用精确导入,不能调用 AssetDatabase.Refresh():
        // 全库刷新会把刚写入的图集再次推入导入流程,进而触发 OnPostprocessAllAssets,
        // 被 Unity 判定为 "infinite import loop"(ZZBF.spriteatlasv2 反复 changed)。
        AssetDatabase.ImportAsset(atlasPath, ImportAssetOptions.ForceSynchronousImport);
    }
    
@@ -308,6 +372,11 @@
        FileName(spriteFilePath, excludePng);
        SpriteAtlas spriteAtlasTmp = AssetDatabase.LoadAssetAtPath(filePath, typeof(UnityEngine.Object)) as SpriteAtlas;
        if (spriteAtlasTmp == null)
        {
            Debug.LogError($"[SpritePack] 无法加载图集,跳过更新: {filePath}");
            return;
        }
        // 获取图集下图片
        List<UnityEngine.Object> packables = new List<UnityEngine.Object>(spriteAtlasTmp.GetPackables());