首先说一个我自己感觉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