0x00 前言
在Unity 2018.4.6之前的版本,有一個和SpriteAtlas打AB包有關的常見問題。即當給Sprite Atlas打AB包時,Sprite Atlas Texture可能會被重復打包。你可以在這里查看這個issue。
本文就來討論一下如何解決這個問題。
0x01 The Issue
首先,我會演示一下這個issue。如下圖所示,有4個sprite,分別為Icon1, Icon2, Icon3 以及 SF Window(來自Unity Samples: UI)。將它們存放到一個叫 new sprite atlas 的新Sprite Atlas中。同時有一個uGUI的Panel使用了其中的一些Sprite來渲染UI元素。


之后使用AssetBundles-Browser分別對UI Canvas和Sprite Atlas打包。

現在,我們可以繼續使用另一個和Assetbundle相關的很贊的工具:
https://github.com/faelenor/asset-bundle-analyzer
來對剛剛打包的Assetbundle的內容進行分析。順便說一下,這個工具是由一位Developer Relations Engineer 開發的,如果有反饋可以到他的工程倉庫提交issue。並且這個工具需要Python2.7來執行,同時由於它的結果會保存到數據庫中,因此最好有一個DB工具例如DB Browser for SQLite來查詢數據庫。
python analyzer.py /Applications/Unity/Unity.app/Contents/Tools ~/projects/MyGame/AssetBundles
Ok,現在我們來看一下我們得到的數據。主表叫做“objects”,每一行數據都來自Assetbundle中的每一個asset。我們可以通過“object_view”視圖來查看其內容。

如上圖所示,canvas和new sprite atlas 這2個Assetbundle都包含了同一個資源——spriteasset texture。我們可以在Editor中找到這張texture。
Editor 中的預覽
0x02 The Solution
那么現在我們要如何解決這個問題呢?這個問題其實是由於所謂的“SpriteAtlas dependencies”所導致的。也就是SpriteAtlas 依賴問題。在SpriteAtlas的inspector編輯器上有一個叫做“Include in Build”的選項。這個選項開啟時,會建立具體的sprite和SpriteAtlas的依賴關系,也就是說SpriteAtlas資源會隨着具體的sprite走,就像Unity中其他asset之間產生依賴那樣。
相反,如果不勾選該選項,sprite會解除它和SpriteAtlas的依賴關系。因此,SpriteAtlas也就不會自動添加到sprite所在的ab中。之后或在運行時,就可以使用所謂的“LateBinding”來加載和綁定對應的sprite了。
https://docs.unity3d.com/Manual/LateBinding.html
具體如何做呢?首先不勾選“Include in Build”選項,之后再在C#腳本中注冊SpriteAtlasManager.atlasRequested 的回調。在這個回調中加載對應的sprite。
https://docs.unity3d.com/ScriptReference/U2D.SpriteAtlasManager-atlasRequested.html
void OnEnable()
{
SpriteAtlasManager.atlasRequested += RequestAtlas;
}
void OnDisable()
{
SpriteAtlasManager.atlasRequested -= RequestAtlas;
}
void RequestAtlas(string tag, System.Action<SpriteAtlas> callback)
{
var ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/new sprite atlas");
var sa = ab.LoadAsset<SpriteAtlas>(tag);
callback(sa);
}
現在,再用AssetBundle Analyzer這個工具來查看一下這次AssetBundle中的數據吧。可以看到此時只有一個spriteatlas的texture打包進了ab中。

ok,還記得本文一開始時說過的嗎?是的,這是一個Unity2018.4.6之前的issue。在Unity 2018.4.6中,Unity已經修復了這個問題。

