UGUI一键刷新(创建)图集、自动生成图集

UI目录

目录结构.png
两个自定义类
#if UNITY_EDITOR

//Debug.Log(Regex.IsMatch(path, "Assets/UI/Modules/.[a-zA-Z0-9]*/Images/.[a-zA-Z0-9]*/.[^/]*.png"));
//Debug.Log(Regex.IsMatch(path, "Assets/UI/Modules/.[^/]*/Images/.[^/]*/.[^/]*.png"));

/// <summary>
/// 图片路径
/// </summary>
public class SpriteTemp
{
    /// <summary>
    /// 图片是不是UI模块
    /// </summary>
    public bool isUI;
    /// <summary>
    /// 图片所在模块
    /// </summary>
    public string moduleName;
    /// <summary>
    /// 图片父路径
    /// </summary>
    public string parentPath;
    /// <summary>
    /// 图片所在的图集名
    /// </summary>
    public string atlasName;

    public SpriteTemp(string path)
    {
        path = path.Replace("\\", "/");
        string[] pathSplit = path.Split('/');
        if (pathSplit.Length == 7)
        {
            if (pathSplit[1].Equals("UI") && pathSplit[2].Equals("Modules") && pathSplit[4].Equals("Images") && pathSplit[6].Contains(".png"))
            {
                this.isUI = true;
                this.moduleName = pathSplit[3];
                this.parentPath = $"Assets/UI/Modules/{this.moduleName}/Images/{pathSplit[5]}";
                this.atlasName = $"Atlas_{this.moduleName}_{pathSplit[5]}.spriteatlas";
                return;
            }
        }
        this.isUI = false;
    }
}


/// <summary>
/// 一个路径是不是UIAtlas路径
/// </summary>
public class AtlasTemp
{
    public bool isAtlas;
    /// <summary>
    /// 图集所在模块名
    /// </summary>
    public string moduleName;
    /// <summary>
    /// 图集的父文件路径
    /// </summary>
    public string parentPath;
    /// <summary>
    /// 图集的名字
    /// </summary>
    public string atlasName;

    public AtlasTemp(string path)
    {
        string[] pathSplit = path.Split('/');
        if (pathSplit.Length == 6)
        {
            if (pathSplit[1].Equals("UI") && pathSplit[2].Equals("Modules") && pathSplit[4].Equals("Images"))
            {
                this.isAtlas = true;
                this.moduleName = pathSplit[3];
                this.parentPath = $"Assets/UI/Modules/{this.moduleName}/Images/{pathSplit[5]}";
                this.atlasName = $"Atlas_{this.moduleName}_{pathSplit[5]}.spriteatlas";
                return;
            }
        }
        this.isAtlas = false;
    }
}



#endif
监听资源导入
using UnityEngine;
using UnityEditor;

public class AssetImportEditor : AssetPostprocessor
{

    //这里要重新整理,把删除、移动、添加的方法拆分开
    public static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssets)
    {
        //Debug.Log("OnPostprocessAllAssets");

        foreach (string assetPath in importedAssets)
        {
            Debug.Log("导入资源 : " + assetPath);
        }

        ImportSpriteEditor.DeletedSprite(deletedAssets);
        ImportSpriteEditor.MoveSprite(movedAssets, movedFromAssets);

    }

    //--导入贴图前
    public void OnPreprocessTexture()
    {
        Debug.Log("导入贴图前 OnPreprocessTexture");
        ImportSpriteEditor.TextureToSprite(assetPath, assetImporter);
    }

    //--导入精灵后
    public void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
    {
        Debug.Log("导入精灵后 " + assetPath);
        AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceSynchronousImport);

        ImportSpriteEditor.AddSprites(assetPath, texture);

    }

    //--导入贴图后
    public void OnPostprocessTexture(Texture2D texture2D)
    {
        //Debug.Log("导入贴图后 OnPostprecessTexture");
    }
    public void OnPreprocessAudio()
    {
        Debug.Log("导入声音前 OnPreprocessAudio");
        AudioImporter audioImporter = (AudioImporter)assetImporter;
        Debug.Log(string.Format("路径 :{0}", audioImporter.assetPath));
    }
    //--导入声音后
    public void OnPostprocessAudio(AudioClip clip)
    {
        Debug.Log("导入声音后 OnPostprocessAudio");
    }

    //--导入模型前
    public void OnPreprocessModel()
    {
        Debug.Log("导入模型前 OnPreprocessModel");
        ModelImporter modelImporter = (ModelImporter)assetImporter;
    }

    //--导入模型后
    public void OnPostprocessModel(GameObject gameObject)
    {
        Debug.Log("导入模型后 OnPostprocessModel");
    }

    //--导入动画前
    public void OnPreprocessAnimation()
    {
        Debug.Log("导入动画前 OnPreprocessAnimation");
        ModelImporter modelImporter = (ModelImporter)assetImporter;
    }
    //--导入动画后
    public void OnPostprocessAnimation(GameObject gameObject, AnimationClip animationClip)
    {
        Debug.Log("导入动画后 OnPostprocessAnimation");
    }

    //--导入材质后
    public void OnPostprocessMaterial(Material material)
    {
        Debug.Log("导入材质后 OnPostprocessMaterial");
    }

}

检查是否是UGUI模块
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class ImportSpriteEditor : Editor
{
    static SpriteTemp add_sprite_temp = null;
    static Dictionary<string, SpriteTemp> deleted_sprite_refresh = new Dictionary<string, SpriteTemp>();
    static Dictionary<string, SpriteTemp> move_sprite_refresh = new Dictionary<string, SpriteTemp>();

    public static void TextureToSprite(string assetPath, AssetImporter assetImporter)
    {
        SpriteTemp spriteTemp = new SpriteTemp(assetPath);
        if (spriteTemp.isUI)
        {
            //是UI模块
            TextureImporter textureImporter = (TextureImporter)assetImporter;
            textureImporter.alphaSource = TextureImporterAlphaSource.FromInput;
            textureImporter.alphaIsTransparency = true;
            textureImporter.isReadable = false;
            textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
            textureImporter.textureType = TextureImporterType.Sprite;
            //textureImporter.spritePackingTag = $"UIAtlas_{atlasData.moduleName}_{atlasData.fileName}";
            textureImporter.SaveAndReimport();
            TextureImporterPlatformSettings platformSetting = new TextureImporterPlatformSettings()
            {
                maxTextureSize = 1024,
                resizeAlgorithm = TextureResizeAlgorithm.Bilinear,
                format = TextureImporterFormat.Automatic,
                textureCompression = TextureImporterCompression.Compressed,
                crunchedCompression = false
            };
            textureImporter.SetPlatformTextureSettings(platformSetting);
        }
    }

    public static void AddSprites(string assetPath, Texture2D texture)
    {
        add_sprite_temp = null;
        SpriteTemp spriteTemp = new SpriteTemp(assetPath);
        if (spriteTemp.isUI)
        {
            Debug.Log($"添加UI : {assetPath}");
            add_sprite_temp = spriteTemp;

            //int value1 = texture.width % 4;
            //int value2 = texture.height % 4;
            //if (value1 != 0 || value2 != 0)
            //{
            //    Debug.LogError($"图片不符合规范,纹理的长宽都是4的倍数,才能被压缩成DXT5格式,图片位置:{assetPath}");
            //}
        }
        EditorApplication.delayCall += onDelayCalls_Add;
    }

    static void onDelayCalls_Add()
    {
        if (add_sprite_temp != null)
        {
            AtlasEditor.RefreshSpriteAtlas(add_sprite_temp.parentPath, add_sprite_temp.atlasName);
        }
        EditorApplication.delayCall -= onDelayCalls_Add;
    }

    public static void DeletedSprite(string[] assetPaths)
    {
        if (assetPaths.Length <= 0) return;
        deleted_sprite_refresh.Clear();
        for (int i = 0; i < assetPaths.Length; i++)
        {
            SpriteTemp spriteTemp = new SpriteTemp(assetPaths[i]);
            if (spriteTemp.isUI && deleted_sprite_refresh.ContainsKey(spriteTemp.parentPath) == false)
            {
                deleted_sprite_refresh.Add(spriteTemp.parentPath, spriteTemp);
            }
        }
        EditorApplication.delayCall += onDelayCalls_Deleted;
    }
    static void onDelayCalls_Deleted()
    {
        foreach (var item in deleted_sprite_refresh)
        {
            SpriteTemp spriteTemp = item.Value;
            AtlasEditor.RefreshSpriteAtlas(spriteTemp.parentPath, spriteTemp.atlasName);
        }
        EditorApplication.delayCall -= onDelayCalls_Deleted;
    }

    public static void MoveSprite(string[] movedAssets, string[] movedFromAssets)
    {
        if (movedAssets.Length <= 0) return;
        move_sprite_refresh.Clear();
        for (int i = 0; i < movedAssets.Length; i++)
        {
            string newPath = movedAssets[i];
            string oldPath = movedFromAssets[i];
            //刷新 oldPath Atlas 
            SpriteTemp old_spriteTemp = new SpriteTemp(oldPath);
            if (old_spriteTemp.isUI && move_sprite_refresh.ContainsKey(old_spriteTemp.parentPath) == false)
            {
                move_sprite_refresh.Add(old_spriteTemp.parentPath, old_spriteTemp);
            }
            //刷新 newPath Atlas
            SpriteTemp new_spriteTemp = new SpriteTemp(newPath);
            if (new_spriteTemp.isUI && move_sprite_refresh.ContainsKey(new_spriteTemp.parentPath) == false)
            {
                move_sprite_refresh.Add(new_spriteTemp.parentPath, new_spriteTemp);
            }
        }
        EditorApplication.delayCall += onDelayCalls_Move;
    }
    static void onDelayCalls_Move()
    {
        foreach (var item in move_sprite_refresh)
        {
            SpriteTemp spriteTemp = item.Value;
            AtlasEditor.RefreshSpriteAtlas(spriteTemp.parentPath, spriteTemp.atlasName);
        }
        EditorApplication.delayCall -= onDelayCalls_Move;
    }

}

创建图集
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;

public class AtlasEditor : Editor
{

    [MenuItem("Tools/刷新(创建)图集")]
    public static void onCreateAtlas()
    {
        string rootPath = Path.Combine(Application.dataPath, "UI/Modules");
        //获取文件夹下的一级子文件夹
        string[] allModule = Directory.GetDirectories(rootPath);
        foreach (string modulePath in allModule)
        {
            //模块下是否存在方图片的文件夹
            //Images下不允许直接方图片,需要放在Images的子文件夹中,如:Images/Common,Images/bg 等
            string imagesDire = Path.Combine(modulePath, "Images");
            bool isExists = Directory.Exists(imagesDire);
            if (isExists)
            {
                string[] allImagesDire = Directory.GetDirectories(imagesDire);
                foreach (string imageDire in allImagesDire)
                {
                    string direPath = "Assets" + imageDire.Substring(Application.dataPath.Length);
                    direPath = direPath.Replace("\\", "/");
                    AtlasTemp atlasTemp = new AtlasTemp(direPath);
                    if (atlasTemp.isAtlas)
                    {
                        RefreshSpriteAtlas(atlasTemp.parentPath, atlasTemp.atlasName);
                    }
                }
            }
        }
    }


    public static void RefreshSpriteAtlas(string parentPath, string atlasName)
    {
        Debug.Log("RefreshSpriteAtlas  " + parentPath);
        string atlasPath = $"{parentPath}/{atlasName}";

        _ClearSpriteAtlas(parentPath, atlasName);

        SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(atlasPath);

        string[] spritePathArr = Directory.GetFiles(parentPath, "*.png");

        if (spritePathArr.Length <= 0)
        {
            if (atlas != null)
            {
                AssetDatabase.DeleteAsset(atlasPath);
            }
            return;
        }

        if (atlas == null)
        {
            _isCreateSpriteAtlas(atlasPath, spritePathArr);
        }
        else
        {
            _isRefreshSpriteAtlas(atlas, spritePathArr);
        }

        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    static void _isRefreshSpriteAtlas(SpriteAtlas atlas, string[] spritePathArr)
    {
        Dictionary<string, Sprite> keyValues = new Dictionary<string, Sprite>();
        for (int i = 0; i < spritePathArr.Length; i++)
        {
            string spritePath = spritePathArr[i].Replace("\\", "/");
            Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
            if (sprite != null)
            {
                string spriteName = Path.GetFileNameWithoutExtension(spritePath);
                keyValues.Add(spriteName, sprite);
            }
        }

        var spriteArr = SpriteAtlasExtensions.GetPackables(atlas);
        var SpriteAtlasExtensions_Type = typeof(SpriteAtlasExtensions);
        var RemoveAt = SpriteAtlasExtensions_Type.GetMethod("RemoveAt", BindingFlags.Static | BindingFlags.NonPublic);
        for (int i = spriteArr.Length - 1; i >= 0; i--)
        {
            if (spriteArr[i] == null)
            {
                RemoveAt.Invoke(null, new[] { atlas, (object)i });
            }
            else
            {
                string name = spriteArr[i].name;
                if (keyValues.ContainsKey(name))
                {
                    keyValues.Remove(name);
                }
                else
                {
                    RemoveAt.Invoke(null, new[] { atlas, (object)i });
                }
            }
        }
/*
        SerializedObject serializedObject = new SerializedObject(atlas);
        SerializedProperty packables = serializedObject.FindProperty("m_EditorData.packables");
        for (int i = packables.arraySize - 1; i >= 0; i--)
        {
            SerializedProperty texsp = packables.GetArrayElementAtIndex(i);
            string spritePath = texsp.objectReferenceValue != null ? AssetDatabase.GetAssetPath(texsp.objectReferenceValue) : string.Empty;
            //string spriteParent = string.IsNullOrEmpty(spritePath) ? string.Empty : Path.GetDirectoryName(spritePath).Replace("\\", "/");
            //if (string.IsNullOrEmpty(spriteParent) || spriteParent != atlasTemp.parentPath || keyValuePairs.ContainsKey(spritePath) == false)
            //{
            //    texsp.objectReferenceValue = null;
            //    packables.DeleteArrayElementAtIndex(i);
            //}
            if (!string.IsNullOrEmpty(spritePath) && keyValues.ContainsKey(spritePath))
            {
                keyValues.Remove(spritePath);
            }
            else
            {
                texsp.objectReferenceValue = null;
                packables.DeleteArrayElementAtIndex(i);
            }
        }
        serializedObject.ApplyModifiedProperties();
*/
        List<Sprite> spriteList = new List<Sprite>();
        foreach (var item in keyValues)
        {
            spriteList.Add(item.Value);
        }
        atlas.Add(spriteList.ToArray());

    }

    static void _isCreateSpriteAtlas(string atlasPath, string[] spritePathArr)
    {
        SpriteAtlas atlas = _CreateSpriteAtlas(atlasPath);
        List<Sprite> sprites = new List<Sprite>();
        for (int i = 0; i < spritePathArr.Length; i++)
        {
            string spritePath = spritePathArr[i].Replace("\\", "/");
            Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
            if (sprite != null)
            {
                sprites.Add(sprite);
            }
        }
        atlas.Add(sprites.ToArray());
/*
        //SerializedObject serializedObject = new SerializedObject(atlas);
        //SerializedProperty packables = serializedObject.FindProperty("m_EditorData.packables");
        //for (int i = 0; i < sprites.Count; i++)
        //{
        //    packables.InsertArrayElementAtIndex(i);
        //    packables.GetArrayElementAtIndex(i).objectReferenceValue = sprites[i];
        //}
        //serializedObject.ApplyModifiedProperties();
*/
    }

    static void _ClearSpriteAtlas(string parentPath, string atlasName)
    {
        string[] allAtlas = Directory.GetFiles(parentPath, "*.spriteatlas");
        foreach (string atlasPath in allAtlas)
        {
            //获取此文件夹下所有图集并删除不符合规范的图集
            string name = Path.GetFileName(atlasPath);
            if (atlasName.Equals(name) == false)
            {
                //删除不符合命名规范的图集
                AssetDatabase.DeleteAsset(atlasPath);
            }
        }
    }
    /// <summary>
    /// 创建一个图集
    /// </summary>
    /// <param name="atlasPath"></param>
    /// <returns></returns>
    static SpriteAtlas _CreateSpriteAtlas(string atlasPath)
    {
        SpriteAtlas atlas = new SpriteAtlas();
        //此选项为false时,需要手写atlas加载方法:SpriteAtlasManager.atlasRequested += void
        atlas.SetIncludeInBuild(true);
        SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings()
        {
            blockOffset = 1,
            enableRotation = false,
            enableTightPacking = false,
            padding = 4,
        };
        atlas.SetPackingSettings(packSetting);
        SpriteAtlasTextureSettings textureSetting = new SpriteAtlasTextureSettings()
        {
            readable = false,
            generateMipMaps = false,
            sRGB = true,
            filterMode = FilterMode.Bilinear,
        };
        atlas.SetTextureSettings(textureSetting);
        AssetDatabase.CreateAsset(atlas, atlasPath);
        return atlas;
    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容