日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity中使用TexturePacker优化图集

發布時間:2024/3/26 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity中使用TexturePacker优化图集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自: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文件中各個小圖的信息

    總結

    以上是生活随笔為你收集整理的Unity中使用TexturePacker优化图集的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。