Unity-UGUI SpriteAtlas打包圖集工具

SpriteAtlas


SpriteAtlas 是Unity2017新增得UGUI圖集工具,與之前版本的圖集工具SpritePacker對比,參考上一篇文章:

https://blog.csdn.net/u014794120/article/details/100126439

上篇文章提供了兩種圖集打包方式的優缺點,以及UGUI在使用過程中DrawCall問題的優化,本篇主要提供SpriteAtlas打包批處理工具的分享。

 

AtlasAutoPacker


AtlasAutoPacker,提供了四個基礎圖集打包的規則:

  • 根據路徑配置,自動批處理打包
  • 選中路徑下所有Sprite資源打包(包含子文件夾),逐個添加方式
  • 選中路徑下所有Sprite資源打包(不包含子文件夾),逐個添加方式
  • 完全打包一個Folder,添加整個Folder

支持圖集壓縮格式Format、Compressor Quality、默認設置

支持SpriteAtlas ImportSetiing選項設置,Include In Build、AllowRotation,Tight Packing,Pading、ReadWrite Enable……

 

Code


代碼如下:
 

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

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章