using UnityEditor; using UnityEditor.U2D; using UnityEngine; using System.Collections.Generic; /// /// 批量将所有贴图和图集的 WebGL 平台格式改为 ETC2 压缩。 /// 根据原始格式自动判断是否需要 Alpha 通道: /// - 有 Alpha → ETC2_RGBA8 /// - 无 Alpha → ETC2_RGB4 /// /// 使用菜单:程序/Sprite/WebGL贴图转ETC2 /// public class ConvertWebGLTextureToETC2 { [MenuItem("程序/Sprite/WebGL贴图转ETC2(全部)")] public static void ConvertAll() { ConvertTextures(); ConvertSpriteAtlases(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } [MenuItem("程序/Sprite/WebGL贴图转ETC2(仅贴图)")] public static void ConvertTexturesOnly() { ConvertTextures(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } [MenuItem("程序/Sprite/WebGL贴图转ETC2(仅图集)")] public static void ConvertAtlasesOnly() { ConvertSpriteAtlases(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } static void ConvertTextures() { var guids = AssetDatabase.FindAssets("t:Texture2D", new[] { "Assets/ResourcesOut" }); int total = guids.Length; int converted = 0; int skipped = 0; for (int i = 0; i < total; i++) { var assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); EditorUtility.DisplayProgressBar("WebGL贴图转ETC2", $"[{i + 1}/{total}] {assetPath}", (float)i / total); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer == null) { skipped++; continue; } bool needsAlpha = NeedsAlpha(importer); var targetFormat = needsAlpha ? TextureImporterFormat.ETC2_RGBA8 : TextureImporterFormat.ETC2_RGB4; var webGLSettings = importer.GetPlatformTextureSettings("WebGL"); // 已经是目标格式则跳过 if (webGLSettings.overridden && webGLSettings.format == targetFormat) { skipped++; continue; } webGLSettings.overridden = true; webGLSettings.maxTextureSize = GetMaxTextureSize(importer); webGLSettings.textureCompression = TextureImporterCompression.Compressed; webGLSettings.format = targetFormat; webGLSettings.compressionQuality = 50; importer.SetPlatformTextureSettings(webGLSettings); importer.SaveAndReimport(); converted++; Debug.Log($"[ETC2] 贴图 {(needsAlpha ? "RGBA8" : "RGB4")}: {assetPath}"); } EditorUtility.ClearProgressBar(); Debug.Log($"[ETC2] 贴图处理完成:转换 {converted},跳过 {skipped},共 {total}"); EditorUtility.DisplayDialog("贴图转换完成", $"转换 {converted} 个,跳过 {skipped} 个,共 {total} 个贴图。", "OK"); } static void ConvertSpriteAtlases() { var guids = AssetDatabase.FindAssets("t:SpriteAtlas", new[] { "Assets/ResourcesOut" }); int total = guids.Length; int converted = 0; int skipped = 0; for (int i = 0; i < total; i++) { var assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); EditorUtility.DisplayProgressBar("WebGL图集转ETC2", $"[{i + 1}/{total}] {assetPath}", (float)i / total); try { var importer = SpriteAtlasImporter.GetAtPath(assetPath) as SpriteAtlasImporter; if (importer == null) { skipped++; continue; } var webGLSettings = importer.GetPlatformSettings("WebGL"); // 判断 Alpha:检查其他平台的设置来推断 bool needsAlpha = AtlasNeedsAlpha(importer); var targetFormat = needsAlpha ? TextureImporterFormat.ETC2_RGBA8 : TextureImporterFormat.ETC2_RGB4; if (webGLSettings.overridden && webGLSettings.format == targetFormat) { skipped++; continue; } webGLSettings.overridden = true; webGLSettings.maxTextureSize = 2048; webGLSettings.textureCompression = TextureImporterCompression.Compressed; webGLSettings.format = targetFormat; webGLSettings.compressionQuality = 50; importer.SetPlatformSettings(webGLSettings); importer.SaveAndReimport(); converted++; Debug.Log($"[ETC2] 图集 {(needsAlpha ? "RGBA8" : "RGB4")}: {assetPath}"); } catch (System.Exception ex) { Debug.LogError($"[ETC2] 图集处理失败 {assetPath}: {ex.Message}"); } } EditorUtility.ClearProgressBar(); Debug.Log($"[ETC2] 图集处理完成:转换 {converted},跳过 {skipped},共 {total}"); EditorUtility.DisplayDialog("图集转换完成", $"转换 {converted} 个,跳过 {skipped} 个,共 {total} 个图集。", "OK"); } /// /// 判断贴图是否需要 Alpha 通道 /// static bool NeedsAlpha(TextureImporter importer) { // 1. 检查贴图本身是否含 Alpha if (importer.DoesSourceTextureHaveAlpha()) return true; // 2. 检查已有平台设置的格式来推断 foreach (var platform in new[] { "Android", "iPhone", "Standalone" }) { var settings = importer.GetPlatformTextureSettings(platform); if (settings.overridden && IsAlphaFormat(settings.format)) return true; } // 3. 检查 alphaSource 设置 if (importer.alphaSource != TextureImporterAlphaSource.None) return importer.DoesSourceTextureHaveAlpha(); return false; } /// /// 判断图集是否需要 Alpha(通过检查其他平台的格式推断) /// static bool AtlasNeedsAlpha(SpriteAtlasImporter importer) { foreach (var platform in new[] { "Android", "iPhone", "Standalone" }) { var settings = importer.GetPlatformSettings(platform); if (settings.overridden && IsAlphaFormat(settings.format)) return true; } // 图集默认认为需要 Alpha(UI 图集大多有透明) return true; } /// /// 判断格式是否包含 Alpha 通道 /// static bool IsAlphaFormat(TextureImporterFormat format) { switch (format) { case TextureImporterFormat.RGBA32: case TextureImporterFormat.RGBA16: case TextureImporterFormat.ARGB32: case TextureImporterFormat.ARGB16: case TextureImporterFormat.DXT5: case TextureImporterFormat.ETC2_RGBA8: case TextureImporterFormat.ASTC_4x4: case TextureImporterFormat.ASTC_5x5: case TextureImporterFormat.ASTC_6x6: case TextureImporterFormat.ASTC_8x8: case TextureImporterFormat.ASTC_10x10: case TextureImporterFormat.ASTC_12x12: case TextureImporterFormat.PVRTC_RGBA2: case TextureImporterFormat.PVRTC_RGBA4: return true; default: return false; } } /// /// 获取已有的最大贴图尺寸设置 /// static int GetMaxTextureSize(TextureImporter importer) { foreach (var platform in new[] { "Android", "iPhone", "Standalone" }) { var settings = importer.GetPlatformTextureSettings(platform); if (settings.overridden) return settings.maxTextureSize; } return importer.maxTextureSize; } }