Unity3D - 使用TexturePacker打包圖集以及NGUI對旋轉sprites的支持

做者:EnigmaJJpython

博客地址:http://www.cnblogs.com/twjcnblog/app

 

 

在Unity中使用NGUI時,爲了減小draw call,咱們會將美術用到的小圖打成一張圖集,如圖:函數

 

打包圖集有不少種方式,這裏介紹的是使用TexturePacker工具來打包圖集。TexturePacker支持的遊戲引擎至關的普遍,主要包含了Unity、Cocos2D、SpriteKit、LibGDX等等,導出的圖片格式也十分豐富,能夠導出爲PSD、PNG、TGA、JPG等等,而且能夠經過命令行方式來使用它。工具

 

在遊戲開發過程當中,美術的小圖資源是不須要存放到遊戲工程中的,由於遊戲工程中咱們只會使用打包以後的圖集。例如美術的小圖資源存放在UIResources文件夾下,與Assets同級:spa

而在UIResources文件夾中存放的每一個子文件夾中的小圖最終都會被打包成一張圖集,例如UIResources下有Battle文件夾,Battle文件夾中的小圖以下:命令行

最終這些小圖就會被打包成一張圖集,存放在Assets/Resources/UIAtlas文件夾下:code

 

這裏咱們要介紹的就是這樣的自動化打包腳本,使用python開發。咱們定義的texture_packer.py文件內容以下:orm

 1 import os
 2 
 3 IMAGE_EXT = [".jpg", ".jpeg", ".png", ".tga", ".bmp"]
 4 ATLAS_OUTPUT_PATH = os.path.abspath("..\\..") + "\\Assets\\Resources\\UIAtlas"
 5 def export_atlas(atlas_name, images_path):
 6     file_list = ""
 7     for dir_name in os.listdir(images_path):
 8         path_name = os.path.join(images_path, dir_name)
 9         if not os.path.isfile(path_name):
10             continue
11 
12         # 判斷文件類型
13         file_ext = os.path.splitext(path_name)[1].lower()
14         if not (file_ext in IMAGE_EXT):
15             print(file_ext)
16             continue
17 
18         # 有些圖片多是棄用的可是美術不想刪掉的,或者是美術用來給程序拼界面輔
19         # 助行的,對於這些圖片咱們要過濾掉,能夠給這些圖片名字裏加上中文來區分
20         for character in dir_name:
21             if (u'\u4e00' <= character <= u'\u9fff'):
22                 continue
23 
24         file_list = file_list + path_name + " "
25 
26     if not os.path.exists(ATLAS_OUTPUT_PATH):
27         os.makedirs(ATLAS_OUTPUT_PATH)
28 
29     arguments = "--format unity "\
30                 "--max-width 1024 --max-height 1024 "\
31                 "--size-constraints POT "\
32                 "--sheet " + ATLAS_OUTPUT_PATH + "\\" + atlas_name + ".png "\
33                 "--data " + ATLAS_OUTPUT_PATH + "\\" + atlas_name + ".txt "\
34                 + file_list
35 
36     result = os.system("texturepacker " + arguments)
37     if (0 != result):
38         # 打圖集失敗,多是圖片在指定大小的一張圖集中打不下,嘗試打成多個圖集
39         arguments_multi = "--format unity " \
40                     "--max-width 1024 --max-height 1024 " \
41                     "--multipack " \
42                     "--sheet " + ATLAS_OUTPUT_PATH + "\\" + atlas_name + "_{n}.png " \
43                     "--data " + ATLAS_OUTPUT_PATH + "\\" + atlas_name + "_{n}.txt " \
44                     + file_list
45         os.system("texturepacker " + arguments_multi)

代碼的第三、4行咱們定義了圖片可能的後綴格式以及最終打包後的圖集輸出到工程中的文件路徑。export_atlas函數主要作的事情就是遍歷由images_path變量指定的文件路徑下全部的文件,若是是咱們要找的圖片,就添加到待打包的圖片列表中(file_list變量)。代碼的18到22行咱們過濾掉了被廢棄以及不須要打包的圖片,這些圖片的名字中包含了中文。代碼的29到34行以及39到44行爲最終提交給TexturePacker的打包參數,區別在於後者包含了"--multipack",用於指明能夠打成多個圖集。blog

將texture_packer.py文件放在UIResources文件夾中,在包含小圖的子文件夾Battle中,新建一個Battle.py,用於真正的執行打包操做,代碼以下:遊戲

1 import os
2 import sys
3 
4 sys.path.append("..")
5 import texture_packer
6 
7 atlas_name = os.path.basename(__file__)
8 atlas_name = os.path.splitext(atlas_name)[0]
9 texture_packer.export_atlas(atlas_name, os.path.abspath("."))

這個文件的代碼很簡單,提取文件名做爲圖集的名稱,並將文件所在的文件夾做爲參數傳遞給export_atlas函數。這樣,自動化打包腳本就完成了。

 

在打包圖集時,咱們能夠經過"--disable-rotation"參數來禁止sprite的旋轉,通常都會使用這個參數,這是由於NGUI默認是不支持旋轉的sprite的。可是咱們知道,使用旋轉功能來打包圖集會使得圖集更緊湊,有利於節約空間,特別是對於使用旋轉功能能夠打包到一張圖集中 vs 不使用旋轉功能須要打包到兩張圖集中。下面左圖是沒有啓用旋轉功能,右圖啓用了旋轉功能,能夠發現右圖更緊湊,且預留的空間更大:

 

爲了使用帶旋轉的圖集,咱們就須要調整NGUI的源代碼:

1. 在UISpriteData.cs中,咱們添加如下變量,用於標記sprite是否被旋轉:

 

2. 在NGUIJson.cs的LoadSpriteData(UIAtlas atlas, Hashtable decodedHash)函數中,添加從數據文件中讀取sprite是否被旋轉:

 

3. 接着仍是在NGUIJson.cs的LoadSpriteData(UIAtlas atlas, Hashtable decodedHash)函數中,添加sprite數據的處理代碼:

這裏須要說明下,首先就是長和寬,sprite的旋轉都是順時針旋轉90度的,這是由於任何其餘角度的旋轉都不可能產生比旋轉90度更小的矩形範圍。而在圖集的數據文件中,記錄的是sprite未旋轉的長和寬,所以,在sprite被旋轉90度後,咱們就須要對換他的長和寬:

對於Padding數據也是如此,數據文件中記錄的都是sprite未旋轉的值,所以在sprite旋轉90度後,left padding的值應該賦值給top padding,依次類推。

 

在這些處理完畢後,sprite數據已經所有正確了,可是NGUI顯示的效果仍舊是旋轉的sprite,如圖:

接下來就很簡單了,沒錯,咱們只須要:轉!回!去!

 

4. 在UISprite.cs的SetAtlasSprite函數中,添加以下代碼:

以及在UISprite.cs的OnFill函數中,添加以下代碼:

 

OK,大功告成:

相關文章
相關標籤/搜索