Unity使用Texturepacker打包图集自动替换脚本

首先说一个我自己感觉Unity自带的spriteAtlas坑的地方,我们Prefab上面使用的图片如果是Unity自带的图集工具spriteAtlas打的图集的话,prefab对应的meta文件里面没有对图集的依赖,所以这个时候如果我们只对图集打assetbundle包的话,加载prefab的时候是不知道他到底依赖哪个图集,这就导致加载出来的prefab会出现图片丢失的情况。

上面的问题是我个人测试出来的,不知道是否本人操作有误,如果确是操作有误,欢迎评论指正。

鉴于上面的问题,自然就会想到丢弃Unity的spriteAtlas工具,使用TexturePacker进行打图集,这个工具的使用方法就不多说了,有很多文章都有说明。使用TexturePacker打图集很简单,但是当我们的图集里面有图片的增加或者删除的时候,我们新打的图集导入Unity就需要保留旧的图集的分割信息,比如名字,九宫这些信息,如果直接替换会导致这些信息丢失或者位置不正确,UI自然显示也就不正确了,所以就必须有一个脚本来处理这个问题。

我们要做的是将老的图集的spritesheet相关信息保留下来,然后在导入的时候再将这些信息赋予新的图集的meta文件对应的spritesheet就解决了。

但是这个地方又有一个坑,那就是Unity图集的meta文件里面的spritesheet这个属性,只有在首次导入图片的时候修改才会生效(如有不对欢迎指正),如果这个图片已经导入了,再importer进来去修改这个属性的话是不会生效的,但是TexturePacker生成的文件是一个png一个xml,我们必须先读取到xml信息才能正确设置图集的相关信息,比如图片的切割,九宫等,所以我们就得写个脚本先导入xml再导入png图集,下面直接上代码,自己稍加修改路径就可以使用

#if UNITY_EDITOR

using UnityEngine;

using System.IO;

using UnityEditor;

using System.Collections.Generic;

using System.Xml;

public class UITextureDeal : AssetPostprocessor

{

    static Dictionary<string, Vector4> borderDic = new Dictionary<string, Vector4>();

    void OnPreprocessTexture()
    {
        string fileNameNoSuffix = assetPath.Substring(0, assetPath.LastIndexOf("."));
        Debug.Log("assetPath:" + assetPath);
        //存旧的border信息
        if (assetPath.Contains("GameRes/UIRes"))
        {
            string fileSuffix = assetPath.Substring(assetPath.LastIndexOf(".") + 1);
            string name = fileNameNoSuffix.Substring(assetPath.LastIndexOf("/") + 1);
            if (fileSuffix == "png")
            {
                TextureImporter assetImporter1 = TextureImporter.GetAtPath(assetPath) as TextureImporter;
                SaveBoreder(borderDic, assetImporter1);
                ChangeMeta(fileNameNoSuffix, name, borderDic);
            }
        }
    }

    void ChangeMeta(string fileNameNoSuffix, string name, Dictionary<string, Vector4> borderDic)
    {
        FileStream fs = new FileStream(fileNameNoSuffix + ".xml", FileMode.Open);
        StreamReader sr = new StreamReader(fs);
        string jText = sr.ReadToEnd();
        fs.Close();
        sr.Close();
        XmlDocument xml = new XmlDocument();
        xml.LoadXml(jText);
        XmlNodeList elemList = xml.GetElementsByTagName("sprite");
        XmlElement node = (XmlElement)xml.GetElementsByTagName("TextureAtlas").Item(0);
        WriteMeta(elemList, name, borderDic, int.Parse(node.GetAttribute("height")));
        AssetDatabase.Refresh();
        borderDic.Clear();
    }

    static List<string> GetFiles(string directory, string pattern = "*.*")
    {
        List<string> files = new List<string>();
        foreach (var item in Directory.GetFiles(directory, pattern))
        {
            files.Add(item);
        }
        foreach (var item in Directory.GetDirectories(directory))
        {
            files.AddRange(GetFiles(item, pattern));
        }
        return files;
    }


    [MenuItem("Tools/PackerTexture-Copy")]

    public static void BuildTexturePacker()
    {
        string inputPath = Application.dataPath;
        inputPath = inputPath.Substring(0, inputPath.LastIndexOf("/"));
        inputPath = inputPath.Substring(0, inputPath.LastIndexOf("/")) + "/TexturePackerOutFile";
        string[] imagePath = GetFiles(inputPath).ToArray();
        CopyFile(imagePath, ".xml");
        AssetDatabase.Refresh();
        CopyFile(imagePath, ".png");
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        Debug.LogError("处理完毕");
    }

    static void CopyFile(string[] imagePath, string suffix)
    {
        foreach (string path in imagePath)
        {
            if (Path.GetExtension(path) == suffix)
            {
                string str = path.Substring(path.LastIndexOf("\\") + 1);
                string name = str.Substring(0, str.IndexOf("."));
                string rootPath = string.Format("{0}/GameRes/UIRes/Atlas/{1}", Application.dataPath, name);
                string pngPath = rootPath + "/" + str;
                if (!Directory.Exists(rootPath))
                {
                    Directory.CreateDirectory(rootPath);
                }
                File.Copy(path, pngPath, true);
            }
        }
    }

    //如果这张图集已经拉好了9宫格,需要先保存起来
    /// <summary>
    /// 
    /// </summary>
    /// <param name="tIpterMap">待写入的border数据</param>
    /// <param name="tIpter"></param>
    static void SaveBoreder(Dictionary<string, Vector4> tIpterMap, TextureImporter tIpter)

    {

        for (int i = 0, size = tIpter.spritesheet.Length; i < size; i++)

        {

            tIpterMap.Add(tIpter.spritesheet[i].name, tIpter.spritesheet[i].border);

        }

    }


    //写信息到SpritesSheet里
    /// <summary>
    /// 
    /// </summary>
    /// <param name="elemList">xml文件里面的sprite数据</param>
    /// <param name="sheetName"></param>
    /// <param name="oldborders">旧图集里面的border数据</param>
    void WriteMeta(XmlNodeList elemList, string sheetName, Dictionary<string, Vector4> oldborders, int height)
    {
        string path = string.Format("Assets/GameRes/UIRes/Atlas/{0}/{1}.png", sheetName, sheetName);
        Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
        //要替换的图片
        TextureImporter aImporter = assetImporter as TextureImporter;
        SpriteMetaData[] metaData = new SpriteMetaData[elemList.Count];
        for (int i = 0, size = elemList.Count; i < size; i++)

        {
            XmlElement node = (XmlElement)elemList.Item(i);
            Rect rect = new Rect();
            rect.x = int.Parse(node.GetAttribute("x"));
            rect.y = height - int.Parse(node.GetAttribute("y")) - int.Parse(node.GetAttribute("h"));
            rect.width = int.Parse(node.GetAttribute("w"));
            rect.height = int.Parse(node.GetAttribute("h"));
            metaData[i].rect = rect;
            metaData[i].pivot = new Vector2(0.5f, 0.5f);
            string xmlName = node.GetAttribute("n");
            string name = xmlName.Substring(0, xmlName.IndexOf("."));
            metaData[i].name = name;
            if (oldborders.ContainsKey(name))
            {
                metaData[i].border = oldborders[name];
            }
        }
        aImporter.textureType = TextureImporterType.Sprite;
        aImporter.spriteImportMode = SpriteImportMode.Multiple;
        aImporter.mipmapEnabled = false;
        aImporter.spritesheet = metaData;
        aImporter.SaveAndReimport();
    }


}


#endif

猜你喜欢

转载自blog.csdn.net/u014417405/article/details/129924841