談談我用Unity5的AssetBundle踩到的幾個坑


在上段時間摸索了Unity5的assetbundle用法之后,我在項目里面全面的使用起來,於是發現了一些坑,這里和大家分享一下,順便說說我是怎樣解決的。

首先是圖集打包的問題。這個問題在unity5.2版本已經解決了,但在5.2之前確實是一個bug來的。具體的表現是,你把同一個圖集標簽的散圖打包成同一個assetbundle時,這個assetbundle既包含了圖集的大圖,也包含了散圖本身,變成了重復打包,容量暴增。這個問題困擾了我一小段時間,后來嘗試着下載了個unity5.2,就沒有這個問題了,圖集散圖打包成一個assetbundle,只會保留圖集的大圖作為texture2d,那些散圖全部都只有sprite,沒有texture2d了。
第二個問題,其實也是圖集引起的。具體表現是如果你的UI(指的是UGUI)上面使用了圖集,然后把UI的預設打包Assetbundle,那么就算UI依賴的圖集本身已經設置了AssetName,但UI的Assetbundle本身還是會包含圖集的大圖來打包,又重復打包了,容量同樣暴增。這個問題在5.2依然存在。
第三個問題,Unity5的Assetbundle是自動尋找需要重新打包的內容來增量打包的,這個判斷有時候會不准確。具體表現是,比如剛才那些重復打包的內容,我在項目內把圖集取消了,那么所有由於圖集引起的問題就都不存在了,打包出去的Assetbundle就變得很小了,然后再把圖集標簽設置回去,再重新打包Assetbundle,居然發現有時候之前打包變小了的Assetbundle沒有再變回巨大的容量,而在運行的時候也沒有出錯……雖然這好像是好事情,但由於是不穩定的,應該算是一種bug來的,所以不能依靠這種方法來解決問題。
第四個問題,其實不算問題,是Unity對於圖片的處理方式,不過對於項目實際發布時的容量會有影響。比如你把一張只有100多k的圖片放到項目里面,由於Unity會自動幫你把圖片生成為Unity自身的圖片格式,通過自身的設置來對圖片進行壓縮和保存,而導致了100多k的圖片進入項目后就變成了差不多1M的容量。這其實沒有什么問題的,這樣做對於Unity本身來說是一種性能的優化,它可以把圖片更快的轉換成顯卡使用的Texture。但照這個容量打包Assetbundle,會發現原本不大的圖片資源,突然就變得大好幾倍了。從正常的途徑解決,你要么降圖片質量,選擇圖片壓縮方式,或者降圖片尺寸,把圖片變小。但不論你怎么做,對實際的效果還是會有影響的,特別是在ios上面看,色彩位數不夠了,漸變色會變成一塊一塊的。
 
下面來說說解決的辦法。
這些辦法我已經實際的應用在項目里面了,暫時沒發現什么問題。如果各位還有更好的方法,歡迎指教。
首先,我拋棄了通過升級unity版本來解決以上問題。最近Unity的新版本的恐怖程度應該不用我多說什么了,每次出來一個版本,就伴隨着一堆新的bug出現,我怕升級完是跳過了一些坑,但又掉進新的坑里面了。
既然不能靠Unity解決,那么就只能靠自己了。
對於依賴的問題,其實我們也可以完全的不用Unity5的那套新Assetbundle機制,而使用舊版Assetbundle的自己處理依賴的方式,通過push和pop來打包依賴的。雖然這些方法被標記成已過時了,但暫時的版本還能用。不過我同樣也拋棄了這樣的方式,因為既然是標記成已過時方法,雖然現在還能用,但難以保證會不會在下個版本就被徹底拋棄了,這樣風險有點大。
那么還是用Unity5的新機制來打包依賴吧。回頭看一看,前面兩個問題實際上都是由於圖集引起的,所以我決定拋棄Unity的Sprite Packer,而自己寫一套圖集生成方法。其實我之前已經寫過幾次圖集生成的算法了,這次稍微不同的是,我不想手下的人由於我這樣的改動而對原來的制作流程有太大的變化,所以我還是直接讓他們用散圖的sprite來制作UI,只是在實際打包Assetbundle時,會通過我的方法,生成和Unity的Sprite Packer一樣規則的圖片圖集。具體規則就是在圖集最大尺寸可以允許的范圍內,把所有散圖合成一張png,如果超出了最大尺寸,再把超出的散圖打包成第二張、第三張的png。但同一個圖集里面的所有散圖都會保存在同一個配置文件里面,所以只要加載了圖集的配置文件,然后找到具體某個sprite屬於哪張png,就可以按配置生成處理,而由於是同一張png的texture2D生成的sprite,他們的draw call也會是一樣的。這一步反正挺成功的,我把打包和加載的方式稍微改了之后,使用者估計還不知道自己沒有使用Unity的Sprite Packer。不得不說一句,面向對象就是好,邊界明確,本來這樣的修改會牽涉到很多的,但現在只需要小改就行了。
既然圖集打包的問題解決了,那么如果UI上面用了圖集又該怎么辦呢?由於已經是自己生成的png作為圖集,原本打的依賴肯定就不成立了,需要自己去記錄一下。我的做法是在打包UI預設的時候,全部遍歷查找一下有哪些是用到了sprite的,然后把sprite所屬的圖集名稱和sprite的加載名稱記錄下來,然后把UI預設另存一份,把sprite去掉。再用另存的UI預設打包Assetbundle。最后在加載該UI的時候,通過配置知道那些組件上面用了哪個sprite,再在初始化的時候幫他加載回來。這一步也挺成功的,由於是完全自動化的,所以制作者根本不需要管過程,只需要按照正常流程做UI就行了。
既然前面兩個問題解決了,那么第三個問題也沒什么問題了。然后看第四個問題。這個問題其實官方的API上面就有解決辦法,就是把圖片的后綴改成bytes,這樣圖片就變成了TextAsset來加載,加載后再通過bytes來重新生成Texture2D。這樣做了之后,在生成Texture2D的速度上是比Unity幫你保存的大容量的貼圖紋理要慢一點點,但具體慢多少我沒感覺出來。然后好處就是,美術給的圖片是多大,那么我們打包出來的資源容量就是多大,很准確了。
然后,問題就都解決了。我的項目是把所有資源完全外部加載的,編譯內部不包含任何資源,所以這個外部包的大小是很明顯能看出差別的。現在項目還沒有做完,資源不算特別多。在沒有解決那些亂七八糟問題前,外部資源總容量有300多M,壓縮了之后有100多M。解決了之后,外部資源變成只有100M左右,壓縮了之后只有60多M了。由於現在還處於制作階段,所有美術資源還沒開始整理和壓縮容量,相信把美術資源再整理之后,容量就會更小了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM