我不知道從哪里搞到了一張圖集tiles_sheet.png,然后它有一個同名文件tiles_sheet.xml,明顯這個xml保存的是這張圖集的所有切片信息...
但是我也不確定是不是用Texturepacker導出的,所以我也沒用Texturepacker importer來導入它,因為自己通過代碼切割一下也很方便
先曬出圖集信息內容供參考:

tiles_sheet.png

tiles_sheet.xml
如果直接將這兩個東西導入到unity中,那么xml是無效的,只能得到一整張的切片,如果這時候手動去切,或者使用unity自帶的 'Sprite Editor'去自動切割的話也是有問題的,因為這些小切片很多像素都是連在一起的,沒有辦法精確的切開,那既然已經有了xml文件,那肯定還是得利用上最好了...
先說以下3個關鍵的大坑
1.由于unity定義貼圖像素坐標是以左上角為原點的,但是大部分第三方打包圖集工具都是以左下角為原點
2.由于1的原因,導致實際上每個切片數(shù)據(jù)的y值都要重新計算,但是重新計算卻需要得到這場圖片的寬高(有高就行),但是導入時候圖集的寬高并不能通過簡單的API直接得到
3.想到通過AssetDatabase.LoadAssetAtPath去加載這張圖,然后就能獲取到長寬了,但是我們這個自動切片處理過程是在Import的時候執(zhí)行的,這個時候這張圖默認是還沒有導入到AssetDatabase中,也就是說AssetDatabase.LoadAssetAtPath是無法加載到這張圖的...最后為了不引入其他不必要的程序集模塊,最終是通過反射來獲取到的
代碼如下
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Xml;
using System.Reflection;
public class AutoSliceSpriteSheetWithXML : AssetPostprocessor
{
private void OnPreprocessTexture()
{
//獲取各種路徑
string dataPath = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("/") + 1);
string fullPath = dataPath + assetPath;
string fileName_without_extension = Path.GetFileNameWithoutExtension(fullPath);
string extension = Path.GetExtension(fullPath);
string dirPath = Path.GetDirectoryName(fullPath);
string xml_fileName = fileName_without_extension + ".xml";
string xml_fullPath = Path.Combine(dirPath, xml_fileName);
//檢測是否存在同名的.xml文件,不存在則不用左處理
if (File.Exists(xml_fullPath))
{
//根據(jù)XML參數(shù)進行自動進行圖片切割
XmlDocument doc = new XmlDocument();
//加載xml文件
doc.Load(xml_fullPath);
//從xml中讀取第一個節(jié)點,該節(jié)點imagePath是對應圖片的名字,再次確定查看是否和圖片的名字匹配
string target_path = (doc.FirstChild as XmlElement).GetAttribute("imagePath");
if (target_path != fileName_without_extension + extension)
{
throw new System.Exception("當前xml不是對應圖片的xml...");
}
//將導入對象轉換為TextureImporter對象,注意,這里最好在前面加上判斷是否是貼圖文件
var importer = assetImporter as TextureImporter;
//將貼圖文件的類型修改由默認的單張精靈切片修改為多張精靈切片類型
importer.spriteImportMode = SpriteImportMode.Multiple;
//通過反射獲取導入圖片的長和寬,為什么要獲取長和寬,因為unity中以左上角為起點,大部分圖集工具中是以左下角為原點,需要轉換
object[] args = new object[2];
MethodInfo methodInfo = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
methodInfo.Invoke(importer, args);
int texture_width = (int)args[0];
int texture_height = (int)args[1];
//獲取所有的目標節(jié)點
var xml_nodes = doc.FirstChild.ChildNodes;
//新建精靈切片數(shù)據(jù)集合
var spriteMetaDatas = new SpriteMetaData[xml_nodes.Count];
//遍歷所有節(jié)點信息
for (int i = 0; i < xml_nodes.Count; i++)
{
var node = xml_nodes[i];
XmlElement element = node as XmlElement;
//獲取節(jié)點中所帶的信息
string sprite_name = element.GetAttribute("name");
float x = float.Parse(element.GetAttribute("x"));
float y = float.Parse(element.GetAttribute("y"));
float width = float.Parse(element.GetAttribute("width"));
float height = float.Parse(element.GetAttribute("height"));
//re_y是指反向的y,因為unity處理貼圖默認以左上角為原點,大部分圖集工具中是以左下角為原點,從而導致y值錯誤,所以這里重新計算y正確的值
float re_y = texture_height - y - height;
//新建精靈切片數(shù)據(jù)對象用于保存單個切片信息
SpriteMetaData one_SpriteMetaData = new SpriteMetaData();
one_SpriteMetaData.name = sprite_name;
one_SpriteMetaData.alignment = (int)SpriteAlignment.Center;
one_SpriteMetaData.rect = new Rect(x, re_y, width, height);
spriteMetaDatas[i] = one_SpriteMetaData;
}
//將所有精靈切片信息數(shù)據(jù)綁定到TextureImporter上完成設置
importer.spritesheet = spriteMetaDatas;
}
}
}
此時直接將圖片和xml文件拖到unity中,ok,已經按照xml中的配置信息,自動完成切片了...

切片后

切片后