csharp
复制代码
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine.U2D;
using UnityEngine;
using System.Reflection;
namespace LogicEditor.Editor
{
/// <summary>
/// 自动图集生成器
/// 用于自动扫描指定文件夹下的图片资源,并生成对应的Sprite Atlas(精灵图集)
/// 支持多平台压缩格式设置,并验证图集页数不超过限制
/// </summary>
public static class AutoAtlasGenerator
{
// 支持的图片文件扩展名
private static readonly string[] SupportedImageExtensions = { ".png", ".jpg" };
/// <summary>
/// 获取图集打包后的实际页数
/// 使用Unity内部API获取图集预览纹理,从而得到真实的页数
/// </summary>
/// <param name="atlas">要检查的图集对象</param>
/// <param name="atlasPath">图集文件路径</param>
/// <returns>图集页数,无法获取时返回1</returns>
private static int GetPackedPageCount(SpriteAtlas atlas, string atlasPath)
{
// 通过反射获取Unity内部API:SpriteAtlasExtensions.GetPreviewTextures
// 此方法可以获取图集打包后的实际纹理页
var editorAsm = typeof(SpriteAtlasUtility).Assembly;
var extType = editorAsm.GetType("UnityEditor.U2D.SpriteAtlasExtensions");
if (extType != null)
{
var mi = extType.GetMethod("GetPreviewTextures", BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(SpriteAtlas) }, null);
if (mi != null)
{
var textures = mi.Invoke(null, new object[] { atlas }) as Texture2D[];
if (textures != null)
return textures.Length;
}
}
return 1;
}
/// <summary>
/// 处理单个文件夹,为其生成或更新图集
/// </summary>
/// <param name="folderPath">要处理的文件夹路径</param>
/// <param name="outputPath">图集输出路径</param>
private static void ProcessSingleFolder(string folderPath, string outputPath)
{
// 获取文件夹下所有图片文件(单个文件夹进行读取)
string[] imagePaths = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly);
List<Object> validTextures = new List<Object>();
// 筛选有效的图片资源
foreach (var path in imagePaths)
{
bool isValidImage = false;
foreach (var ext in SupportedImageExtensions)
{
if (path.EndsWith(ext))
{
isValidImage = true;
break;
}
}
if (isValidImage)
{
string assetPath = path.Replace(Application.dataPath, "Assets");
Object tex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
if (tex != null)
validTextures.Add(tex);
}
}
// 如果文件夹中没有有效图片,跳过处理
if (validTextures.Count == 0)
return;
// 创建或加载图集
string folderName = new DirectoryInfo(folderPath).Name;
string atlasPath = Path.Combine(outputPath, folderName + ".spriteatlas").Replace("\\", "/");
// 先加载图集, 如果有的话
SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(atlasPath);
if (atlas == null)
{
atlas = new SpriteAtlas();
SetAtlasSettings(atlas);
AssetDatabase.CreateAsset(atlas, atlasPath);
}
// 清空图集并添加新的图片资源
atlas.Remove(atlas.GetPackables());
atlas.Add(validTextures.ToArray());
// 打包图集
SpriteAtlasUtility.PackAtlases(new SpriteAtlas[] { atlas }, EditorUserBuildSettings.activeBuildTarget, false);
AssetDatabase.SaveAssets();
// 验证图集页数
int pageCount = GetPackedPageCount(atlas, atlasPath);
if (pageCount > 1)
{
throw new System.Exception($"图集【{folderPath}】页数为 {pageCount},超出限制,路径:{atlasPath}");
}
else
{
Debug.Log($"图集【{folderPath}】页数为 {pageCount},正常");
}
}
/// <summary>
/// 配置图集的打包设置和平台压缩格式
/// 包括打包参数、纹理设置以及各平台的压缩格式配置
/// </summary>
/// <param name="atlas">要配置的图集对象</param>
public static void SetAtlasSettings(SpriteAtlas atlas)
{
// 打包设置
atlas.SetPackingSettings(new SpriteAtlasPackingSettings
{
padding = 4,
enableRotation = true,
enableTightPacking = false,
enableAlphaDilation = false,
});
// 纹理设置
atlas.SetTextureSettings(new SpriteAtlasTextureSettings
{
sRGB = true,
readable = false,
generateMipMaps = false,
filterMode = FilterMode.Bilinear
});
// 默认平台设置
atlas.SetPlatformSettings(new TextureImporterPlatformSettings
{
name = "DefaultTexturePlatform",
overridden = false,
maxTextureSize = 2048
});
// iOS平台设置:使用ASTC 4x4压缩
atlas.SetPlatformSettings(new TextureImporterPlatformSettings
{
name = "iPhone",
overridden = true,
format = TextureImporterFormat.ASTC_4x4,
compressionQuality = (int)TextureCompressionQuality.Best
});
// Android平台设置:使用ASTC 4x4压缩
atlas.SetPlatformSettings(new TextureImporterPlatformSettings
{
name = "Android",
overridden = true,
format = TextureImporterFormat.ASTC_4x4,
compressionQuality = (int)TextureCompressionQuality.Best,
androidETC2FallbackOverride = AndroidETC2FallbackOverride.UseBuildSettings
});
}
/// <summary>
/// 生成指定路径下的所有图集
/// 扫描源文件夹及其所有子目录,为每个目录生成对应的图集文件
/// </summary>
/// <param name="sourceFolder">源图片文件夹路径</param>
/// <param name="outputFolder">图集输出文件夹路径</param>
public static void GenerateAtlases(string sourceFolder, string outputFolder)
{
// 验证路径是否存在
if (!Directory.Exists(sourceFolder))
{
throw new System.Exception($"源图片文件夹不存在: {sourceFolder}");
}
if (!Directory.Exists(outputFolder))
{
throw new System.Exception($"输出文件夹不存在: {outputFolder}");
}
// 获取所有子目录(包括根目录)
List<string> allDirs = new List<string>();
allDirs.Add(sourceFolder);
allDirs.AddRange(Directory.GetDirectories(sourceFolder, "*", SearchOption.AllDirectories));
// 处理每个目录
foreach (string dir in allDirs)
{
// 跳过包含"_NoNeedAtlas"的目录
if (new DirectoryInfo(dir).Name.Contains("_NoNeedAtlas"))
{
Debug.Log($"忽略目录: {dir}");
continue;
}
ProcessSingleFolder(dir, outputFolder);
}
// 刷新资源数据库
AssetDatabase.Refresh();
Debug.Log($"图集生成完成!");
}
}
}