Unity 之 TexturePacker(TP) 的应用
2016-03-02 10:18
591 查看
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的一些命令行参数。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/a65edc7a01c78b75647ef393afeb1fb2)
下面我们写代码来用上这些命令行参数。写代码之前先看看我们要打成图集的小图们:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/cbd94f8365ed79fccea63fe133f5a88e)
好的,上代码:
运行 Tools/SpritesPacker/CommandBuild,并查看SheetsByTP目录下打包好的图集:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/f246146c9bc8889c65d9856c591ad16b)
发现得到了两个文件,一个就是打包好的大图,及一个XML格式的配置文件:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/2d1f9aea1b96f33307d7914ec2004fb8)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/bab432e1dc6563487ff2fb059d4783f6)
但这样子的图集,unity并不能用,还需要做进一步的处理。这里先说下原理。在Unity里,一张图片的格式很多
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/b4034e17618a5d093806f4436e5aeb53)
不同格式有着不同的用途(UGUI用的是Sprite的格式),当我们往Unity里导入图片时,这张图片是什么格式由TextureImporter类决定,大家可以去看看这个类的API。然后我们再在Unity里随便找到一张图片的 .meta文件,用你喜欢的文本编辑器打开它:
里边有个spriteSheet的项,在 TextureImporter的API里对应
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/8bfdf34a4871bdb2b87470b2d5d8a80b)
发现是一个SpriteMetaData的数组。在看看SpriteMetaData有什么
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/26c0861b4ff1d1237171f8ba35bce50b)
我们只要把这些信息填好就行。上代码:
然后点击 Tools/SpritesPacker/TexturePacker,看看 TexturePacker文件夹,会发现
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/211bddc35e0269037272e49b42a85cdc)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/49bf9251dabdde4b52d0e3c4634f2ea2)
这样Unity就用了,为了验证能用,我们把原来的小图和在TP里打包的图集都删掉,然后创建一些Image,用上我们打包好的图集里的图片。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/1d5b4fa0ece5413c4f086cd07d0e112b)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/06/9af48828ee446673103f9877e5c61d08)
到此就成功地在Unity用上了用TP打包好的图集了。
图片用到的九宫格信息也在这里哦!
其实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打包好的图集了。
图片用到的九宫格信息也在这里哦!
相关文章推荐
- 两种方式登录FTP
- FTP命令大全
- PHP的FTP学习(二)
- 基于Jquery制作的幻灯片图集效果打包下载
- PHP的FTP学习(四)
- 七、HTTP应答状态
- 实现dedecms图集单击图片翻页的功能
- PHP的FTP学习(三)
- smtp邮件发送一例
- android4.0与2.3版本的TP代码区别解析
- unity实现多点触控代码
- 在Unity中实现动画的正反播放代码
- unity实现摄像头跟随
- Unity3D上路_01-2D太空射击游戏
- Unity3D上路_02-第一视角射击游戏
- Unity3D上路_03-塔防游戏
- Unity3D上路_04-基础资源介绍
- Unity3D上路_05-网络相关
- [软件资讯]Unity已支持将3D游戏导出成Flash
- thinkphp 路径 (纯转)