// AtlasProcessor.cs using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEditor.U2D; using UnityEngine; using UnityEngine.U2D; public static class AtlasProcessor { private static readonly HashSet DirtyAtlas = new HashSet(); private static readonly Dictionary> AtlasContents = new Dictionary>(); public static void ForceRebuildAtlases(AtlasConfiguration config) { InitializeAtlasData(config); ProcessAllSprites(config); PackAllAtlases(config); } private static void InitializeAtlasData(AtlasConfiguration config) { AtlasContents.Clear(); var atlasGuids = AssetDatabase.FindAssets("t:SpriteAtlas", new[] { config.atlasOutputPath }); foreach (var guid in atlasGuids) { var path = AssetDatabase.GUIDToAssetPath(guid); var atlas = AssetDatabase.LoadAssetAtPath(path); if (atlas == null) continue; var atlasName = Path.GetFileNameWithoutExtension(path); var packed = atlas.GetPackables(); AtlasContents[atlasName] = new HashSet(); foreach (var obj in packed) { var assetPath = AssetDatabase.GetAssetPath(obj); if (!string.IsNullOrEmpty(assetPath)) { AtlasContents[atlasName].Add(assetPath); } } } } private static void ProcessAllSprites(AtlasConfiguration config) { var allSprites = AssetDatabase.FindAssets("t:Sprite", new[] { config.rawUIPath }); foreach (var guid in allSprites) { var path = AssetDatabase.GUIDToAssetPath(guid); ProcessSingleSprite(path, config); } } public static void ProcessSingleSprite(string path, AtlasConfiguration config) { if (!path.StartsWith(config.rawUIPath)) return; var importer = AssetImporter.GetAtPath(path) as TextureImporter; if (importer == null) return; ConfigureTextureImporter(importer, config); AddToAtlas(path, config); } private static void ConfigureTextureImporter(TextureImporter importer, AtlasConfiguration config) { var changed = false; var settings = new TextureImporterSettings(); importer.ReadTextureSettings(settings); if (importer.textureType != TextureImporterType.Sprite) { importer.textureType = TextureImporterType.Sprite; changed = true; } if (settings.spriteGenerateFallbackPhysicsShape) { settings.spriteGenerateFallbackPhysicsShape = false; importer.SetTextureSettings(settings); changed = true; } ApplyPlatformSettings(importer, "Android", config.androidFormat, config); ApplyPlatformSettings(importer, "iPhone", config.iosFormat, config); ApplyPlatformSettings(importer, "WebGL", config.webglFormat, config); if (changed) importer.SaveAndReimport(); } private static void ApplyPlatformSettings(TextureImporter importer, string platform, TextureImporterFormat format, AtlasConfiguration config) { var settings = importer.GetPlatformTextureSettings(platform); if (!settings.overridden || settings.format != format || settings.compressionQuality != config.compressionQuality) { settings.overridden = true; settings.format = format; settings.compressionQuality = config.compressionQuality; importer.SetPlatformTextureSettings(settings); } } private static void AddToAtlas(string spritePath, AtlasConfiguration config) { var atlasName = GetAtlasName(spritePath, config); if (string.IsNullOrEmpty(atlasName)) return; if (!AtlasContents.TryGetValue(atlasName, out var paths)) { paths = new HashSet(); AtlasContents[atlasName] = paths; } if (paths.Add(spritePath)) DirtyAtlas.Add(atlasName); } private static string GetAtlasName(string path, AtlasConfiguration config) { var relativePath = path.Replace(config.rawUIPath, "").TrimStart('/'); var directory = Path.GetDirectoryName(relativePath); return directory?.Replace("/", "_"); } private static void PackAllAtlases(AtlasConfiguration config) { foreach (var atlasName in DirtyAtlas) { CreateOrUpdateAtlas(atlasName, config); } DirtyAtlas.Clear(); SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget); AssetDatabase.SaveAssets(); } private static void CreateOrUpdateAtlas(string atlasName, AtlasConfiguration config) { if (!System.IO.Directory.Exists(config.atlasOutputPath)) { Directory.CreateDirectory(config.atlasOutputPath); } var path = $"{config.atlasOutputPath}/{atlasName}.spriteatlas"; var atlas = AssetDatabase.LoadAssetAtPath(path) ?? new SpriteAtlas(); ConfigureAtlasSettings(atlas, config); AddSpritesToAtlas(atlas, AtlasContents[atlasName]); if (!AssetDatabase.Contains(atlas)) { AssetDatabase.CreateAsset(atlas, path); } else { EditorUtility.SetDirty(atlas); } } private static void ConfigureAtlasSettings(SpriteAtlas atlas, AtlasConfiguration config) { // Packing Settings var packingSettings = new SpriteAtlasPackingSettings { padding = config.padding, enableRotation = config.enableRotation, blockOffset = config.blockOffset }; atlas.SetPackingSettings(packingSettings); // Texture Settings var textureSettings = new SpriteAtlasTextureSettings { generateMipMaps = false, sRGB = true, filterMode = FilterMode.Bilinear }; atlas.SetTextureSettings(textureSettings); // Platform Settings SetPlatformFormat(atlas, "Android", config.androidFormat, config); SetPlatformFormat(atlas, "iPhone", config.iosFormat, config); SetPlatformFormat(atlas, "WebGL", config.webglFormat, config); } private static void SetPlatformFormat(SpriteAtlas atlas, string platform, TextureImporterFormat format, AtlasConfiguration config) { var settings = atlas.GetPlatformSettings(platform); settings.overridden = true; settings.format = format; settings.compressionQuality = config.compressionQuality; atlas.SetPlatformSettings(settings); } private static void AddSpritesToAtlas(SpriteAtlas atlas, IEnumerable spritePaths) { var packables = new List(); foreach (var path in spritePaths) { var obj = AssetDatabase.LoadAssetAtPath(path); if (obj != null) packables.Add(obj); } atlas.Add(packables.ToArray()); } }