SpriteAtlas 是Unity2017新增得UGUI图集工具,与之前版本的图集工具SpritePacker对比,参考上一篇文章:
https://blog.csdn.net/u014794120/article/details/100126439
上篇文章提供了两种图集打包方式的优缺点,以及UGUI在使用过程中DrawCall问题的优化,本篇主要提供SpriteAtlas打包批处理工具的分享。
AtlasAutoPacker,提供了四个基础图集打包的规则:
根据路径配置,自动批处理打包选中路径下所有Sprite资源打包(包含子文件夹),逐个添加方式选中路径下所有Sprite资源打包(不包含子文件夹),逐个添加方式完全打包一个Folder,添加整个Folder支持图集压缩格式Format、Compressor Quality、默认设置
支持SpriteAtlas ImportSetiing选项设置,Include In Build、AllowRotation,Tight Packing,Pading、ReadWrite Enable……
代码如下:
using System.IO; using UnityEditor; using UnityEditor.U2D; using UnityEngine; using UnityEngine.U2D; using System.Collections.Generic; public class AtlasAutoPacker : Editor { /// <summary> /// 打包图集类型 /// </summary> public enum PackType { DeepAssets = 0, //指定路径下所有Sprite资源,包含子文件夹 Assets = 1, //指定路径下所有Sprite资源,不包含子文件夹 Folder = 2, //打包一个Folder } private static string _atlasPath = "Assets/Resources/GameAssets/Logic/UISpriteAtlases/"; private static string _extention = ".spriteatlas"; private static string _texturePath = "Assets/Resources/GameAssets/UI/New Resources/dabao/"; /// <summary> /// 生成图集操作基础路径 /// 这些路径下的所有子文件夹,除白名单外,一个Fold生成一个图集 /// </summary> private static List<string> _texturePathes = new List<string>() { "Assets/Resources/GameAssets/UI/XXX/", }; /// <summary> /// 每个基础路径下,个别文件夹不能自动打包图集 /// 这些路径下资源不自动打包图集(都是大图、或者小图大图未分类、或者文件夹下有细分的AB规则、只有一张图打了反而浪费) /// 需要手动处理打包 /// </summary> private static Dictionary<string, List<string>> whiteDic = new Dictionary<string, List<string>>() { {"Assets/Resources/GameAssets/UI/New Resources/dabao/" ,new List<string>(){ "aaaaaa", "bbbbbb", } }, {"Assets/Resources/GameAssets/UI/New Resources/gongyong/" ,new List<string>(){ "cccccc", "dddddd", } } }; [MenuItem("Assets/AtlasPacker/AutoPack")] public static void AutoSetAtlasContents() { foreach (var path in _texturePathes) PackPath(path); } [MenuItem("Assets/AtlasPacker/Pack This Folder")] public static void PackThisFolder() { string selectionpath = string.Empty; foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets)) { selectionpath = AssetDatabase.GetAssetPath(obj); if (File.Exists(selectionpath)) { selectionpath = Path.GetDirectoryName(selectionpath); } break; } PackOneFolder(selectionpath, PackType.Folder); } [MenuItem("Assets/AtlasPacker/Pack Folder`s Children")] public static void PackThisFolderChildren() { string selectionpath = string.Empty; foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets)) { selectionpath = AssetDatabase.GetAssetPath(obj); if (File.Exists(selectionpath)) { selectionpath = Path.GetDirectoryName(selectionpath); } break; } PackOneFolder(selectionpath, PackType.Assets); } [MenuItem("Assets/AtlasPacker/Pack All In Folder")] public static void PackAllInThisFolde() { string selectionpath = string.Empty; foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets)) { selectionpath = AssetDatabase.GetAssetPath(obj); if (File.Exists(selectionpath)) { selectionpath = Path.GetDirectoryName(selectionpath); } break; } PackOneFolder(selectionpath, PackType.DeepAssets); } /// <summary> /// resPath 下的每个文件夹资源打成一个图集 /// </summary> /// <param name="resPath"></param> private static void PackPath(string resPath) { DirectoryInfo srcDir = new DirectoryInfo(resPath); if (srcDir != null && srcDir.Exists) { List<string> whiteList = whiteDic.ContainsKey(resPath) ? whiteDic[resPath] : new List<string>(); DirectoryInfo[] dirs = srcDir.GetDirectories(); foreach (var oneDir in dirs) { if (whiteList.Contains(oneDir.Name)) { Debug.LogWarning("PackPath Ignore folder " + oneDir.Name); continue; } string dirPath = FullPath2Relative(oneDir.FullName); PackOneFolder(dirPath, PackType.Folder); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } else { Debug.LogError("Auto Packer Atlas Failed! texture not exit :" + resPath); } } static void PackOneFolder(string folderPath, PackType packType) { List<Object> assets = FilterAssets(folderPath, packType); if (assets.Count > 0) { string atlasPath = AtlasPath(folderPath); SpriteAtlas atlas = GenerateAtlas(); atlas.Add(assets.ToArray()); if (AssetDatabase.DeleteAsset(atlasPath)) Debug.Log(string.Format("Deleta Old Atlas: {0}", atlasPath)); AssetDatabase.CreateAsset(atlas, atlasPath); //设置atlas AssetBundleName 为atlasName //AssetImporter importer = AssetImporter.GetAtPath(atlasPath); //importer.assetBundleName = Path.GetFileNameWithoutExtension(atlasPath); //importer.SaveAndReimport(); Debug.Log(string.Format("Packing Path: {0} into one Atlas: {1} ", folderPath, atlasPath)); } } static List<Object> FilterAssets(string folderPath, PackType packType) { List<Object> objects = new List<Object>(); DefaultAsset folderAsset = AssetDatabase.LoadAssetAtPath(folderPath, typeof(DefaultAsset)) as DefaultAsset; switch (packType) { case PackType.DeepAssets: string[] assetsGUIDs = AssetDatabase.FindAssets("t:texture", new string[] { folderPath }); foreach (var guid in assetsGUIDs) { Sprite sp = AssetDatabase.LoadAssetAtPath<Sprite>(AssetDatabase.GUIDToAssetPath(guid)) as Sprite; if (sp != null) objects.Add(sp); } break; case PackType.Assets: if(Directory.Exists(folderPath)) { DirectoryInfo dir = new DirectoryInfo(folderPath); FileInfo[] files = dir.GetFiles("*", SearchOption.TopDirectoryOnly); foreach(var fi in files) { string spritePath = FullPath2Relative(fi.FullName); Sprite sp = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath); if (sp != null) objects.Add(sp); } } break; case PackType.Folder: if (folderAsset != null) objects.Add(folderAsset); break; default: if (folderAsset != null) objects.Add(folderAsset); break; } return objects; } static string FullPath2Relative(string fullPath) { string relativePath = fullPath.Substring(fullPath.IndexOf("Assets")); relativePath = relativePath.Replace("\\", "/"); return relativePath; } static string AtlasPath(string resFolderPath) { string atlasName = resFolderPath.Substring(resFolderPath.IndexOf("New Resources")); atlasName = atlasName.Replace("/","_"); return resFolderPath + "/" + atlasName + _extention; } private static SpriteAtlas GenerateAtlas() { // 设置参数 可根据项目具体情况进行设置 SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings() { blockOffset = 1, enableRotation = false, enableTightPacking = false, padding = 2, }; SpriteAtlasTextureSettings textureSetting = new SpriteAtlasTextureSettings() { readable = false, generateMipMaps = false, sRGB = true, filterMode = FilterMode.Bilinear, }; SpriteAtlas atlas = new SpriteAtlas(); atlas.SetPackingSettings(packSetting); atlas.SetTextureSettings(textureSetting); ApplyTexturePlatFormCompressSettingDefault(atlas); atlas.SetIncludeInBuild(true); atlas.SetIsVariant(false); return atlas; } private static void ApplyTexturePlatFormCompressSettingDefault(SpriteAtlas atlas) { TextureImporterPlatformSettings textureCompressDefault = new TextureImporterPlatformSettings(); textureCompressDefault.overridden = false; textureCompressDefault.name = "DefaultTexturePlatform"; textureCompressDefault.textureCompression = TextureImporterCompression.Compressed; textureCompressDefault.compressionQuality = (int)UnityEngine.TextureCompressionQuality.Best; atlas.SetPlatformSettings(textureCompressDefault); TextureImporterPlatformSettings textureCompressIOS = new TextureImporterPlatformSettings(); textureCompressIOS.name = "iPhone"; textureCompressIOS.overridden = true; textureCompressIOS.textureCompression = TextureImporterCompression.Compressed; textureCompressIOS.format = TextureImporterFormat.ASTC_RGBA_6x6; textureCompressIOS.compressionQuality = (int)UnityEngine.TextureCompressionQuality.Best; atlas.SetPlatformSettings(textureCompressIOS); TextureImporterPlatformSettings textureCompressAndroid = new TextureImporterPlatformSettings(); textureCompressAndroid.name = "Android"; textureCompressAndroid.overridden = true; textureCompressAndroid.textureCompression = TextureImporterCompression.Compressed; textureCompressAndroid.format = TextureImporterFormat.ASTC_RGBA_6x6; textureCompressAndroid.compressionQuality = (int)UnityEngine.TextureCompressionQuality.Best; atlas.SetPlatformSettings(textureCompressAndroid); } }