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;
}
}