在游戲和VR項目的研發過程中,加載模塊所帶來的效率開銷和內存占用(即“加載效率”、“場景切換速度”等)經常是開發團隊非常頭疼的問題,它不僅包括資源的加載耗時,同時也包含場景物件的實例化和資源卸載等。在我們看來,該模塊的耗時是目前引擎中僅次於渲染的第二大模塊。因此,我們認為非常有必要來跟大家分享一下目前加載模塊的主要性能問題。
我們通過對提交到www.uwa4d.com網站的大量項目進行分析,認為目前加載模塊中最為耗時的性能開銷可以歸結為以下幾類:資源加載、資源卸載、Object的實例化和代碼的序列化等。今天,我們先為大家帶來資源加載中紋理資源的加載性能分析。
這是侑虎科技第48篇原創文章,歡迎轉發分享,未經作者授權請勿轉載。同時如果您有任何獨到的見解或者發現也歡迎聯系我們,一起探討。(QQ群465082844)
資源加載
資源加載是加載模塊中最為耗時的部分,其CPU開銷在Unity引擎中主要體現在Loading.UpdatePreloading和Loading.ReadObject兩項中,相信經常查看Profiler的朋友對這兩項肯定毫不陌生了。
Loading.UpdatePreloading,這一項僅在調用類似LoadLevel(Async)的接口處出現,主要負責卸載當前場景的資源,並且加載下一場景中的相關資源和序列化信息等。下一場景中,自身所擁有的GameObject和資源越多,其加載開銷越大。
在很多項目中,存在另外一種加載方式,即場景為空場景,絕大部分資源和GameObject都是通過OnLevelWasLoaded回調函數中進行加載、實例化和拼合的。對於這種情況,Loading.UpdatePreloading的加載開銷會很小。
Loading.ReadObject,這一項記錄的則是資源加載時的真正資源讀取性能開銷,基本上引擎的主流資源(紋理資源、網格資源、動畫片段等等)讀取均是通過該項來進行體現。可以說,這一項很大程度上決定了項目場景的切換效率。正因如此,我們就當前項目中所用的主流資源進行了大量的測試和分析,下面我們將分析結果與大家一起分享,希望可以幫到正在進行開發的你。
注意事項:本篇文章的資源性能分析主要是針對移動項目而言,因為目前UWA所測評的項目中,移動游戲/應用占比在90%以上。所以,我們選擇首先在移動設備上針對每種資源的加載性能進行分析和總結。
資源加載性能測試代碼
以下為我們測試時所使用的測試代碼,我們將每種資源均制作成一定大小的AssetBundle文件,並逐一通過以下代碼在不同設備上進行加載,以期得到不同硬件設備上的資源加載性能比較。
測試環境
引擎版本:Unity 5.2版本
測試設備:五台不同檔次的移動設備(Android:紅米2、紅米Note2和三星S6,iOS:iPhone 5 和 iPhone 6)
紋理資源
紋理資源是項目加載過程中開銷占用最大的資源之一,其加載效率由其自身大小決定。目前,決定紋理資源大小的因素主要有三種:分辨率、格式和Mipmap是否開啟。
1. 分辨率 & 格式
分辨率和格式是影響紋理資源加載效率的重要因素,因為這兩項的設置對紋理資源的大小影響很大。因此,我們對這兩種因素進行了詳細的測試:
測試1:相同格式、不同分辨率的加載效率測試
我們選取了兩張分辨率為2048x2048的普通紋理資源,並在打成AssetBundle時,將其分辨率最大值分別設置為512x512、1024x1024和2048x20248,紋理格式均設置為ETC1(Android)和PVRTC(iOS)、且關閉Mipmap功能。所以,三組紋理的內存占用分別為256KB、1MB和4MB,其對應AssetBundle大小為156KB、531KB和1.92MB(對於Android平台)、175KB、628KB和2.4MB(對於iOS平台)。Unity 版本為5.2,壓縮格式為默認的LZMA壓縮。
Android平台測試紋理:
我們在五種不同檔次的機型上加載這些紋理資源,為降低偶然性,每台設備上重復進行十次加載操作並將取其平均值作為最終性能開銷。具體測試結果如下表所示。
通過上述測試,我們可以得到以下結論:
1、紋理資源的分辨率對加載性能影響較大,分辨率越高,其加載越為耗時。設備性能越差,其耗時差別越為明顯;
2、設備越好,加載效率確實越高。但是,對於硬件支持紋理(ETC1/PVRTC)來說,中高端設備的加載效率差別已經很小,比如圖中的紅米Note2和三星S6設備,差別已經很不明顯。
測試2:不同格式、相同分辨率的加載效率測試
我們選取了兩張分辨率為1024x1024的普通紋理資源,並在打成AssetBundle時,根據不同平台將其紋理格式分別設置不同格式用於打包。對於Android平台,我們使用ETC1、ETC2、RGBA16和RGBA32四種格式,對於iOS平台,我們使用PVRTC 4BPP、RGBA16和RGBA32三種格式,同時,對於每張紋理均關閉Mipmap功能。所以,三組紋理的內存占用分別為1MB、1MB、4MB 和 8MB(Android平台)/1MB、4MB 和 8MB(iOS平台)。
Android平台測試紋理:
與測試1相同,我們在五種不同檔次的機型上重復進行十次加載操作並將取其平均值作為最終性能開銷。具體測試結果如下圖所示。
Android設備:
iOS設備:
通過上述測試,我們可以得到以下結論:
1、紋理資源的格式對加載性能影響同樣較大,Android平台上,ETC1和ETC2的加載效率最高。同樣,iOS平台上,PVRTC 4BPP的加載效率最高。
2、RGBA16格式紋理的加載效率同樣很高,與RGBA32格式相比,其加載效率與ETC1/PVRTC非常接近,並且設備越好,加載開銷差別越不明顯;
3、RGBA32格式紋理的加載效率受硬件設備的性能影響較大,ETC/PVRTC/RGBA16受硬件設備的影響較低。
注意事項:這里需要指出的是測試中所使用的ETC1和ETC2紋理均為RGB 4Bit格式,所以對於半透明紋理貼圖,需要兩張ETC1格式的紋理進行支持(一張RGB通道,一張Alpha通道)。逐一加載兩張ETC1格式的紋理,其加載效率要低於RGBA16格式,但可以通過加載方式來進行彌補。這一點我們將在后續文章中進行詳細說明。
2. 開啟Mipmap功能
開啟Mipmap功能同樣會增大一部分紋理大小,一般來說,其內存會增加至原始大小的1.33倍。因此,我們對開啟Mipmap功能前后的加載性能進行了詳細的測試:
測試3:開啟/關閉Mipmap功能的加載效率測試
我們仍然使用兩張分辨率為1024x1024的普通紋理資源,分別使用ETC1格式、PVRTC格式、RGBA16格式和RGBA32格式(測試所用紋理與測試2相同),並在打成AssetBundle時,一組開啟Mipmap功能,一組關閉Mipmap功能。
與測試1相同,我們在五種不同檔次的機型上重復進行十次加載操作並將取其平均值作為最終性能開銷。具體測試結果如下圖所示。
Android平台:
iOS平台:
通過上述測試,我們可以看出:開啟Mipmap功能會導致資源加載更為耗時,且設備性能越差,其加載效率影響越大。
通過以上性能測試,我們對於紋理資源的加載建議如下:
1、嚴格控制RGBA32和ARGB32紋理的使用,在保證視覺效果的前提下,盡可能采用“夠用就好”的原則,降低紋理資源的分辨率,以及使用硬件支持的紋理格式。
2、在硬件格式(ETC、PVRTC)無法滿足視覺效果時,RGBA16格式是一種較為理想的折中選擇,既可以增加視覺效果,又可以保持較低的加載耗時。
3、嚴格檢查紋理資源的Mipmap功能,特別注意UI紋理的Mipmap是否開啟。在UWA測評過的項目中,有不少項目的UI紋理均開啟了Mipmap功能,不僅造成了內存占用上的浪費,同時也增加了不小的加載時間。
4、ETC2對於支持OpenGL ES3.0的Android移動設備來說,是一個很好的處理半透明的紋理格式。但是,如果你的游戲需要在大量OpenGL ES2.0的設備上進行運行,那么我們不建議使用ETC2格式紋理。因為不僅會造成大量的內存占用(ETC2轉成RGBA32),同時也增加一定的加載時間。下圖為測試2中所用的測試紋理在三星S3和S4設備上加載性能表現。可以看出,在OpenGL ES2.0設備上,ETC2格式紋理的加載要明顯高於ETC1格式,且略高於RGBA16格式紋理。因此,建議研發團隊在項目中謹慎使用ETC2格式紋理。
正是由於以上加載效率問題,我們在UWA測評報告中加入了對每個檢測到的紋理資源參數的詳細展示,以方便開發團隊可以快速查看資源的使用情況,只需對相關信息列進行排序,即可定位引發性能問題的具體資源。
說明:以上測試數據為我們所用的測試紋理加載數據,需要指出的是,不同紋理的加載效率是不相同的,因為其內容的不同會造成AssetBundle壓縮包大小的不同,進而造成最終加載效率的不同。這里我們給出的具體性能比較,其本意是讓大家通過數據直觀了解到紋理格式、分辨率和Mipmap功能對加載性能的影響。另外,我們后續會進行更多的測試,以期為大家提供更為普遍的測試結果。
以上為紋理資源在加載時的性能測試。關於加載模塊的性能問題,我們會不斷推出網格、音頻等其他資源的加載性能分析、資源卸載性能分析、資源實例化性能分析、不同加載方式的性能分析等一系列技術文章,並對目前UWA所檢測過項目的共性問題進行總結,以期讓大家對項目的加載效率有更加深入的認知,並提升對加載模塊的掌控能力。