首先说一个我自己感觉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
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
{
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
{
List
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宫格,需要先保存起来
///
///
///
/// 待写入的border数据
///
static void SaveBoreder(Dictionary
{
for (int i = 0, size = tIpter.spritesheet.Length; i < size; i++)
{
tIpterMap.Add(tIpter.spritesheet[i].name, tIpter.spritesheet[i].border);
}
}
//写信息到SpritesSheet里
///
///
///
/// xml文件里面的sprite数据
///
/// 旧图集里面的border数据
void WriteMeta(XmlNodeList elemList, string sheetName, Dictionary
{
string path = string.Format("Assets/GameRes/UIRes/Atlas/{0}/{1}.png", sheetName, sheetName);
Texture2D texture = AssetDatabase.LoadAssetAtPath
//要替换的图片
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