轉自:https://blog.csdn.net/Happy_zailing/article/details/87190150
TexturePacker是一款非常牛逼的打圖集軟件,是一款收費軟件。這是它的官網:https://www.codeandweb.com/texturepacker,大家可以下到最新版本。即便如此,網上還是有很多破解版的(雖然不是最新版的),但是已經夠用了。
其實Unity本身也有圖集打包功能,但Unity並不想讓開發者知道圖集這個概念。開發的過程中,如果你不想知道圖集的存在,Unity完全可以幫你隱藏得很深,但其實它還在幫你打圖集。對於這種打圖集方式,我很不放心。我還是想像傳統那樣的自己打圖集,並且能看到打好的圖集在哪裏,長什麼樣,但又能被Unity所識別,即在Unity裏能用。那TP就可以派上用場了。這是我用的3.0.3版本的TP。大家可以到這裏下載
:http://pan.baidu.com/s/1bgjlHs。關於TP的用法,本文並不做介紹。本文要做的就是利用TP的命令行來實現完全自動化的圖集打包。
打開命令行工具並CD到TexturePacker的安裝目錄,輸入 TexturePacker –help,會出現該版本的TP的一些命令行參數。
下面我們寫代碼來用上這些命令行參數。寫代碼之前先看看我們要打成圖集的小圖們:
好的,上代碼:
-
#if UNITY_EDITOR
-
using UnityEngine;
-
using System.IO;
-
using UnityEditor;
-
using System.Text;
-
using System.Diagnostics;
-
public class CommandBuild : Editor
-
{
-
[MenuItem("Tools/SpritesPacker/CommandBuild")]
-
public static void BuildTexturePacker()
-
{
-
//選擇並設置TP命令行的參數和參數值
-
string commandText = " --sheet {0}.png --data {1}.xml --format sparrow --trim-mode None --pack-mode Best --algorithm MaxRects --max-size 2048 --size-constraints POT --disable-rotation --scale 1 {2}" ;
-
string inputPath = string.Format ("{0}/Images", Application.dataPath);//小圖目錄
-
string outputPath = string.Format ("{0}/TexturePacker", Application.dataPath);//用TP打包好的圖集存放目錄
-
string[] imagePath = Directory.GetDirectories (inputPath);
-
for (int i = 0; i < imagePath.Length; i++)
-
{
-
UnityEngine.Debug.Log (imagePath [i]);
-
StringBuilder sb = new StringBuilder("");
-
string[] fileName = Directory.GetFiles(imagePath[i]);
-
for (int j = 0; j < fileName.Length; j++)
-
{
-
string extenstion = Path.GetExtension(fileName[j]);
-
if (extenstion == ".png")
-
{
-
sb.Append(fileName[j]);
-
sb.Append(" ");
-
}
-
UnityEngine.Debug.Log("fileName [j]:" + fileName[j]);
-
}
-
string name = Path.GetFileName(imagePath [i]);
-
string outputName = string.Format ("{0}/TexturePacker/{1}/{2}", Application.dataPath,name,name);
-
string sheetName = string.Format("{0}/SheetsByTP/{1}", Application.dataPath, name);
-
//執行命令行
-
processCommand("D:\\Program Files (x86)\\CodeAndWeb\\TexturePacker\\bin\\TexturePacker.exe", string.Format(commandText, sheetName, sheetName, sb.ToString()));
-
}
-
AssetDatabase.Refresh();
-
}
-
private static void processCommand(string command, string argument)
-
{
-
ProcessStartInfo start = new ProcessStartInfo(command);
-
start.Arguments = argument;
-
start.CreateNoWindow = false;
-
start.ErrorDialog = true;
-
start.UseShellExecute = false;
-
if(start.UseShellExecute){
-
start.RedirectStandardOutput = false;
-
start.RedirectStandardError = false;
-
start.RedirectStandardInput = false;
-
} else{
-
start.RedirectStandardOutput = true;
-
start.RedirectStandardError = true;
-
start.RedirectStandardInput = true;
-
start.StandardOutputEncoding = System.Text.UTF8Encoding.UTF8;
-
start.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8;
-
}
-
Process p = Process.Start(start);
-
if(!start.UseShellExecute)
-
{
-
UnityEngine.Debug.Log(p.StandardOutput.ReadToEnd());
-
UnityEngine.Debug.Log(p.StandardError.ReadToEnd());
-
}
-
p.WaitForExit();
-
p.Close();
-
}
-
}
-
#endif
運行 Tools/SpritesPacker/CommandBuild,並查看SheetsByTP目錄下打包好的圖集:
發現得到了兩個文件,一個就是打包好的大圖,及一個XML格式的配置文件:
但這樣子的圖集,unity並不能用,還需要做進一步的處理。這裏先說下原理。在Unity裏,一張圖片的格式很多
不同格式有着不同的用途(UGUI用的是Sprite的格式),當我們往Unity裏導入圖片時,這張圖片是什麼格式由TextureImporter類決定,大家可以去看看這個類的API。然後我們再在Unity裏隨便找到一張圖片的 .meta文件,用你喜歡的文本編輯器打開它:
-
fileFormatVersion: 2
-
guid: 542eed357a373ac4186621aa69a5ae78
-
timeCreated: 1456884951
-
licenseType: Pro
-
TextureImporter:
-
fileIDToRecycleName: {}
-
serializedVersion: 2
-
mipmaps:
-
mipMapMode: 0
-
enableMipMap: 1
-
linearTexture: 0
-
correctGamma: 0
-
fadeOut: 0
-
borderMipMap: 0
-
mipMapFadeDistanceStart: 1
-
mipMapFadeDistanceEnd: 3
-
bumpmap:
-
convertToNormalMap: 0
-
externalNormalMap: 0
-
heightScale: .25
-
normalMapFilter: 0
-
isReadable: 0
-
grayScaleToAlpha: 0
-
generateCubemap: 0
-
cubemapConvolution: 0
-
cubemapConvolutionSteps: 8
-
cubemapConvolutionExponent: 1.5
-
seamlessCubemap: 0
-
textureFormat: -1
-
maxTextureSize: 2048
-
textureSettings:
-
filterMode: -1
-
aniso: -1
-
mipBias: -1
-
wrapMode: -1
-
nPOTScale: 1
-
lightmap: 0
-
rGBM: 0
-
compressionQuality: 50
-
allowsAlphaSplitting: 0
-
spriteMode: 0
-
spriteExtrude: 1
-
spriteMeshType: 1
-
alignment: 0
-
spritePivot: {x: .5, y: .5}
-
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
-
spritePixelsToUnits: 100
-
alphaIsTransparency: 0
-
textureType: -1
-
buildTargetSettings: []
-
spriteSheet:
-
sprites: []
-
spritePackingTag:
-
userData:
-
assetBundleName:
-
assetBundleVariant:
裏邊有個spriteSheet的項,在 TextureImporter的API裏對應
發現是一個SpriteMetaData的數組。在看看SpriteMetaData有什麼
我們只要把這些信息填好就行。上代碼:
-
#if UNITY_EDITOR
-
using UnityEngine;
-
using System;
-
using System.IO;
-
using UnityEditor;
-
using System.Collections.Generic;
-
using System.Xml;
-
public class MySpritesPacker : Editor
-
{
-
[MenuItem("Tools/SpritesPacker/TexturePacker")]
-
public static void BuildTexturePacker()
-
{
-
string inputPath = string.Format("{0}/SheetsByTP/", Application.dataPath);
-
string[] imagePath = Directory.GetFiles(inputPath);
-
foreach (string path in imagePath)
-
{
-
if (Path.GetExtension(path) == ".png" || Path.GetExtension(path) == ".PNG")
-
{
-
string sheetPath = GetAssetPath(path);
-
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(sheetPath);
-
Debug.Log(texture.name);
-
string rootPath = string.Format("{0}/TexturePacker/{1}", Application.dataPath,texture.name);
-
string pngPath = rootPath + "/" + texture.name + ".png";
-
TextureImporter asetImp = null;
-
Dictionary<string, Vector4> tIpterMap = new Dictionary<string,Vector4>();
-
if (Directory.Exists(rootPath))
-
{
-
if(File.Exists(pngPath))
-
{
-
Debug.Log("exite: " + pngPath);
-
asetImp = GetTextureIpter(pngPath);
-
SaveBoreder(tIpterMap, asetImp);
-
File.Delete(pngPath);
-
}
-
File.Copy(inputPath + texture.name + ".png", pngPath);
-
}
-
else
-
{
-
Directory.CreateDirectory(rootPath);
-
File.Copy(inputPath + texture.name + ".png", pngPath);
-
}
-
AssetDatabase.Refresh();
-
FileStream fs = new FileStream(inputPath + texture.name + ".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("SubTexture");
-
WriteMeta(elemList, texture.name, tIpterMap);
-
}
-
}
-
AssetDatabase.Refresh();
-
}
-
//如果這張圖集已經拉好了9宮格,需要先保存起來
-
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);
-
}
-
}
-
static TextureImporter GetTextureIpter(Texture2D texture)
-
{
-
TextureImporter textureIpter = null;
-
string impPath = AssetDatabase.GetAssetPath(texture);
-
textureIpter = TextureImporter.GetAtPath(impPath) as TextureImporter;
-
return textureIpter;
-
}
-
static TextureImporter GetTextureIpter(string path)
-
{
-
TextureImporter textureIpter = null;
-
Texture2D textureOrg = AssetDatabase.LoadAssetAtPath<Texture2D>(GetAssetPath(path));
-
string impPath = AssetDatabase.GetAssetPath(textureOrg);
-
textureIpter = TextureImporter.GetAtPath(impPath) as TextureImporter;
-
return textureIpter;
-
}
-
//寫信息到SpritesSheet裏
-
static void WriteMeta(XmlNodeList elemList, string sheetName,Dictionary<string,Vector4> borders)
-
{
-
string path = string.Format("Assets/TexturePacker/{0}/{1}.png", sheetName, sheetName);
-
Texture2D texture = AssetDatabase.LoadAssetAtPath <Texture2D>(path);
-
string impPath = AssetDatabase.GetAssetPath(texture);
-
TextureImporter asetImp = TextureImporter.GetAtPath(impPath) 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 = texture.height - int.Parse(node.GetAttribute("y")) - int.Parse(node.GetAttribute("height"));
-
rect.width = int.Parse(node.GetAttribute("width"));
-
rect.height = int.Parse(node.GetAttribute("height"));
-
metaData[i].rect = rect;
-
metaData[i].pivot = new Vector2(0.5f, 0.5f);
-
metaData[i].name = node.GetAttribute("name");
-
if (borders.ContainsKey(metaData[i].name))
-
{
-
metaData[i].border = borders[metaData[i].name];
-
}
-
}
-
asetImp.spritesheet = metaData;
-
asetImp.textureType = TextureImporterType.Sprite;
-
asetImp.spriteImportMode = SpriteImportMode.Multiple;
-
asetImp.mipmapEnabled = false;
-
asetImp.SaveAndReimport();
-
}
-
static string GetAssetPath(string path)
-
{
-
string[] seperator = { "Assets" };
-
string p = "Assets" + path.Split(seperator, StringSplitOptions.RemoveEmptyEntries)[1];
-
return p;
-
}
-
}
-
internal class TextureIpter
-
{
-
public string spriteName = "";
-
public Vector4 border = new Vector4();
-
public TextureIpter() { }
-
public TextureIpter(string spriteName, Vector4 border)
-
{
-
this.spriteName = spriteName;
-
this.border = border;
-
}
-
}
-
#endif
然後點擊 Tools/SpritesPacker/TexturePacker,看看 TexturePacker文件夾,會發現
這樣Unity就用了,爲了驗證能用,我們把原來的小圖和在TP裏打包的圖集都刪掉,然後創建一些Image,用上我們打包好的圖集裏的圖片。
到此就成功地在Unity用上了用TP打包好的圖集了。
圖片用到的九宮格信息也在這裏哦!
-----------------------------------------------------------修改相關bug-----------------------------------------------------
在上文代碼中
-
using System.IO;
-
using UnityEditor;
-
using System.Collections.Generic;
-
using System.Xml;
-
public class MySpritesPacker : Editor
-
{
-
[MenuItem("Tools/SpritesPacker/TexturePacker")]
-
public static void BuildTexturePacker()
-
{
-
string inputPath = string.Format("{0}/SheetsByTP/", Application.dataPath);
-
string[] imagePath = Directory.GetFiles(inputPath);
-
foreach (string path in imagePath)
-
{
-
if (Path.GetExtension(path) == ".png" || Path.GetExtension(path) == ".PNG")
-
{
-
string sheetPath = GetAssetPath(path);
-
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(sheetPath);
-
Debug.Log(texture.name);
-
string rootPath = string.Format("{0}/LuaFramework/Art/Atlas/{1}", Application.dataPath, texture.name);
-
string pngPath = rootPath + "/" + texture.name + ".png";
-
//TextureImporter asetImp = null;
-
Dictionary<string, Vector4> tIpterMap = new Dictionary<string, Vector4>();
-
if (Directory.Exists(rootPath))
-
{
-
if (File.Exists(pngPath))
-
{
-
Debug.Log("exite: " + pngPath);
-
//因爲用TexturePacker打圖集的時候軟件並不會記錄原圖的九宮信息,所以保存的九宮信息都是默認的(0,0,0,0),此處註釋掉,在生成圖集meta文件的時候重新添加九宮信息
-
//asetImp = GetTextureIpter(pngPath);
-
//SaveBoreder(tIpterMap, asetImp);
-
File.Delete(pngPath);
-
}
-
File.Copy(inputPath + texture.name + ".png", pngPath);
-
}
-
else
-
{
-
Directory.CreateDirectory(rootPath);
-
File.Copy(inputPath + texture.name + ".png", pngPath);
-
}
上文中保存的是打出圖集的九宮切圖,原圖各個小圖的九宮切圖信息丟失
故在生成圖集的meta文件的時候去讀取了原圖的meta文件的九宮切圖信息,添加到圖集的meta文件中(圖集的meta文件中有記錄各個文件的信息的數組)
-
//寫信息到SpritesSheet裏
-
static void WriteMeta(XmlNodeList elemList, string sheetName, Dictionary<string, Vector4> borders)
-
{
-
string path = string.Format("Assets/LuaFramework/Art/Atlas/{0}/{1}.png", sheetName, sheetName);
-
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
-
string impPath = AssetDatabase.GetAssetPath(texture);
-
TextureImporter asetImp = TextureImporter.GetAtPath(impPath) 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 = texture.height - int.Parse(node.GetAttribute("y")) - int.Parse(node.GetAttribute("height"));
-
rect.width = int.Parse(node.GetAttribute("width"));
-
rect.height = int.Parse(node.GetAttribute("height"));
-
metaData[i].rect = rect;
-
metaData[i].pivot = new Vector2(0.5f, 0.5f);
-
metaData[i].name = node.GetAttribute("name");
-
//讀取源文件的meta文件,獲取spriteBorder九宮信息,寫進圖集中
-
string _path = string.Format("{0}/LuaFramework/Art/{1}/{2}.png", Application.dataPath,sheetName, node.GetAttribute("name"));
-
Vector4 _border = GetTextureIpter(_path).spriteBorder;
-
//if (borders.ContainsKey(metaData[i].name))
-
//{
-
metaData[i].border = _border;
-
//}
-
}
-
asetImp.spritesheet = metaData;
-
asetImp.textureType = TextureImporterType.Sprite;
-
asetImp.spriteImportMode = SpriteImportMode.Multiple;
-
asetImp.mipmapEnabled = false;
-
asetImp.SaveAndReimport();
-
}
下圖是原圖的九宮切圖信息
下圖是圖集meta文件中各個小圖的信息