#每天一個小目標#Unity技術分享(九)
【技術小札】是UWA推出的技術交流欄目,我們會將開發團隊中反饋的常見問題加以總結並梳理在此,以供大家參考。同時如果你也是個熱愛分享、願與大家抱團進步的程序員,歡迎加入UWA的QQ群(465082844),與我們奇文分享,疑義相析。
本期為大家精選幾個關於AssetBundle打包的問題,AssetBundle是個坑爹又絕妙的設計,要摸清其原理可是相當不易。建議大家多參考下我們之前的推文:
1、你應該知道的AssetBundle管理機制
2、揭開AssetBundle廬山真面目(一)
3、揭開AssetBundle廬山真面目(二)
————————————————————————————————————————
Q1:Resource的場景下有兩個場景Scene1.unity和Scene2.unity。我要對這些文件進行打包,生成了
Scene1.assetbundle nScene1.assetbundle.meta nScene2.assetbundle nScene2.assetbundle.metan
如果我有相同的資源,理論上它會在這兩個包里各存一份,這樣就造成了包體過大。所以有沒有辦法把共享資源做成依賴項單獨打包,這樣的話每個場景就不會過大了。Unity 5.x的BuildAssetBundles打包機制是否和Unity 4.x不一樣?原來的打包機制已經被剔除了嗎?
用Unity 4.x 的 Push/Pop 是可以抽出相同的資源,並且據我們所知該方法在Unity 5.x 中也受用。根據Unity 5.x新的打包機制,只要把相同資源的 AssetBundle Name 設置好,打包時就會自動抽出來。
————————————————————————————————————————
Q2: 我們在使用Unity 4.3.4開發項目的過程中會遇到鎖屏後主線程卡死的問題,因此我們考慮將Unity版本降至4.1.2,但是因為之前用Unity 4.3.4版本打包的資源比較多,所以想諮詢下有沒有方法可以用Unity 4.1.2 載入 Unity 4.3.4 打包出的AssetBundle?
Unity 4.x 系列中各個版本 AssetBundle 是不兼容的,高版本載入低版本也有可能出現問題,所以一旦版本改動(特別是跨了大版本的改動,如 Unity 4.3 到 Unity 4.5 或者Unity 4.5 到 Unity 4.6 等等)都是需要重新打包 AssetBundle 的。
————————————————————————————————————————
Q3:如果先Destroy Prefab ,然後將Prefab中用到的AssetBundle再進行Unload,這樣的順序是否會有問題 ? 我在手機上測試時發現這樣做內存中就會一直存在,不釋放;如果反過來, 就可以釋放。另外,我是在Destroy 的時候調用的Resources.UnloadUnusedAssets();,請問這會影響最終的結果嗎?
確實可能發生這種情況,在 Resources.UnloadUnusedAssets(); 時,如果還沒有進行AssetBunlde的Unload 操作,那麼從AssetBunlde中載入的資源依然會因為被AssetBunlde引用而無法被卸載。 開發團隊可以嘗試 Destory 後做 AssetBunlde的Unload,最後進行 Resources.UnloadUnusedAssets(); 。
————————————————————————————————————————
Q4: 我們將Shader放到了Resource的目錄下,也已加到Editor的GraphicSetting里,也試過在載入一個空的Prefab時綁定對應的Shader。 但該Shader在Editor里無法正常顯示,看運行時指向是有的,重新指一下就能顯示了, 然而打包以後在手機上顯示正常。
這確實是Unity已知的一個問題,Android 和 iOS 的部分Shader在打包後,在Editor 下無法正常顯示。 主要原因是在打包時,只會把對應平台的Shader預編譯代碼(如 gles )打入包中,因此在 Editor 下會執行失敗(通常 Editor 是 d3d 驅動)。 因此,目前只能嘗試在Editor下重新指定Shader來繞過這個問題。
————————————————————————————————————————
Q5: 我們在UWA上進行了性能測試,發現安卓上同步載入AssetBundle資源會非常耗CPU, 所以近期對資源載入方式做了比較大的調整,絕大部分的資源使用非同步載入的形式。 不過這裡有個疑問想諮詢下: AssetBundle.LoadAsync 和 WWW載入方式都可以用來非同步載入AssetBundle, 但是兩者API特點也不同, 目前看WWW更耗內存一些, 請問這兩種方式更建議使用哪一種 ?
AssetBundle.LoadAsync 是在獲取了 AssetBundle 對象之後載入其中的資源的;而 WWW 載入是在獲取 AssetBundle,兩者的作用是不同的。
開發者可能是希望了解非同步載入 AssetBundle 的幾個 API 之間的區別,相關的介面如下:
new WWW nWWW.LoadFromCacheOrDownloadn
這兩種方式的具體區別可先參考《你應該知道的AssetBundle管理機制》中的「AssetBundle載入進階」部分。
————————————————————————————————————————
Q6: 現在生成AssetBundle的時候每個文件會多生成一個Manifest文件,這個文件也需要一起隨著AssetBundle上傳嗎,在資源載入的時候具體怎麼用呢?
每個文件多生成的Manifest 文件是不需要上傳的,其作用就是供開發人員查看AssetBundle 中的依賴關係等信息。
但除了每個文件多生成的 Manifest 以外,根目錄下還會有一個與根目錄同名的AssetBundle 以及 Manifest 文件,通過運行時載入這個AssetBundle,可以得到一個 AssetBundleManifest 對象,然後就可以通過這個對象得到AssetBundle直接的依賴關係。
更多信息可以參考Unity - Scripting API: AssetBundleManifest
推薦閱讀:
※Cloud Performance Platform:基於PProf的性能分析雲平台
※UWA優化日廈門站回顧 | 資深TA教你如何將藝術概念轉化為渲染代碼
※你應該知道的AssetBundle管理機制
※千億特徵流式學習在大規模推薦排序場景的應用
※Unity3D回合制手游《星辰奇緣》性能測評深度分析