Q&A——資源管理(八)

資源管理

Q1: 我使用Shader.WarmupAllShaders操作,在後續加載資源還是有CreateGPUProgram出現。(Shader都在一個AssetBundle文件中,都是常駐內存的,不會刪掉)是必須使用ShaderVariantCollection來加載Shader嗎?

A:以上這種問題的較大可能是:Shader被打包到不同AssetBundle中了,WarmupAllShaders僅能對當前內存中的Shader進行warm up。後續如果又有Shader加載進來,則仍然會出現CreateGPUProgram操作。

建議開發團隊使用UWA的資源檢測工具,檢測下AssetBundle中Shader的具體打包情況,查看是否出現了冗餘打包的問題。


資源管理

Q2: iOS上方形POT圖片有時候會失真,請問這種情況如何避免?一張NPOT的圖變換成POT,是否有推薦的方法? 採用 ToLarger 的模式拉成POT是否會有損失呢?

A:如果可以的話,建議直接將其製作成POT圖片,而非進行二次轉換。ToLarger確實可以將紋理拉伸成POT紋理,但如果是UI界面(開啓Pixel Perfect)的話,可能顯示時會有較大視覺損失。

資源管理

Q3:AssetBundle在使用時解壓出來的資源會佔用一定的內存。我們現在想嘗試使用兩種加載方式:(1)在AssetBundle加載相關的資源後,將資源進行緩存,並卸載AssetBundle文件;(2)對AssetBundle文件進行緩存,以後用到相關資源後再進行直接進行加載。請問這兩種方式你們推薦哪一種比較好?

A:對於Unity 5.3版本之前的項目,建議通過LoadFromCacheOrDownload或LoadFromFile的方式來加載AssetBundle,這樣既可以降低Assetbundle對象的內存佔用,又可以保持AssetBundle與資源之間的鏈接關係,從而方便後續具有依賴關係的Prefab的加載。

對於Unity 5.3版本之後的項目,可以從AssetBundle打包本身進行處理。即:使用LZ4格式的AssetBundle文件,而不使用默認的LZMA格式。同樣可以達到上述的需求,稍有不足的是,LZ4格式的AssetBundle文件較之LZMA格式的文件佔用稍大。

如果是依賴關係打包,對於被依賴的共享資源AssetBundle文件,我們還是建議將其緩存在內存中,雖有一定的內存增加,但可以通過上述辦法極大地降低內存上的佔用,緩解內存壓力。

資源管理

Q4:在Unity 5.x版本下,我們在用UGUI的過程中發現它把圖集都打進了包裏,這樣就不能自動更新了,請問圖集怎麼做自動更新呢?

在Unity 5.x中UGUI使用的Atlas確實是不可見的,因此無法直接將其獨立打包。但我們建議,可以把Packing Tag相同的源紋理文件,打到同一個AssetBundle中(設置一樣的AssetBundle Name),從而避免Atlas的冗餘。同時這樣打包可以讓依賴它的Canvas的打包更加自由,即不需要把依賴它的Canvas都打在一個AssetBundle中,在更新時直接更新Atlas所在的AssetBundle即可。


資源管理

Q5:圖中的Material.SetPassFast佔用很高,這是我在第一次實例化一個特效,但是第二次實例化就不會出現高值了,請問能怎麼優化嗎?

請輸入圖片描述

該過程是在處理Shader,Unity 5.3以後在第一次顯示時纔會將Shader進行Warmup,所以就會造成一次峯值卡頓。研發團隊可以參考我們之前的分享:Unity加載模塊深度解析之Shader篇以加深理解。


資源管理

Q6: UWA建議“儘可能將靜態UI元素和頻繁變化的動態UI元素分開,存放於不同的Panel下。同時,對於不同頻率的動態元素也建議存放於不同的Panel中。”那麼請問,如果把特效放在Panel裏面,需要把特效拆到動態的裏面嗎?

通常特效是指粒子系統,而粒子系統的渲染和UI是獨立的,僅能通過Render Order來改變兩者的渲染順序,而粒子系統的變化並不會引起UI部分的重建,因此特效的放置並沒有特殊的要求。


資源管理

Q7:我在UWA上進行了性能檢測,在資源內存這裏看到詳情如下。請問這個數量峯值大於1是不是就是有問題的?但一個Material是很可能被實例化多份的。實例化後對象釋放掉,然後清理掉原始的Material,按道理就不算冗餘吧?畢竟大部分都是材質在操作,對貼圖資源應該沒有影響。而且,如果確實有那麼多角色同屏怎麼辦呢?
請輸入圖片描述

是的,如果數量峯值>1,則說明存在資源冗餘的風險。如果是Material實例化,那麼後者是有個(instance)後綴的,比較好識別。如果是new Material(Shader)出來的,那麼是沒有instance後綴的。但無論是哪種方式,如果數量峯值較大,都應引起大家注意。一般都是可以通過其他方法來儘可能避免冗餘的。

如果變化不是隨機的,且Material參數變化情況比較少,那麼可以根據參數的變化情況只做幾種Material,然後通過腳本動態賦值。如果是隨機或者動畫,那就沒什麼辦法了,要麼改需求,要麼就接受這麼多。


資源管理

Q8: 對NGUI字體錯亂有什麼好的解決方案嗎?

有這麼幾種可能:

  1. 一次展開文字太多了。這種情況在部分高通機型和Unity早期版本上都經常出現,現在也偶爾有,究其原理是FontTexture的擴容操作做得不夠快或者收到了硬件驅動的限制。
    一般來說有兩種方法可以解決:(1)減少面板中的字體內容;(2)一開始就用超大量的字體去擴容,將動態字體的FontTexture擴大到足夠大;

  2. 文字渲染與開發團隊編寫的多線程渲染髮生了衝突。這種情況也常有發生,特別是通過GL.IssuePluginEvent方式來開啓多線程渲染的項目,就會容易出現問題。

就我們的優化經驗來看,第一種情況發生的可能性比較大。


資源管理

Q9:我們測試發現,當Animator Controller掛載的動作比較多時,即使切換成另外一個動作很少的Animator Controller,任務的動作信息還是不會釋放。我們將英雄打成一個AssetBundle,然後又把定製的Runtime Animator Controller加載替換進去,英雄自帶的Runtime Animator Controller是掛了所有動作的。我們試了替換Runtime Animator Controller之後,把先前的Runtime Animator Controller Destroy掉,貌似內存也沒釋放。
請輸入圖片描述
請輸入圖片描述

銷燬Animator Controller並不會釋放其內所引用的AnimationClip資源的,所以內存沒有明顯下降是正常的。建議按照以下方式做個試驗:

  1. 銷燬Animator Controller 後,通過Unity Profiler立刻真機Take Sample,查看Animation Clip的Ref count是否爲0;
  2. 如果不是,則需要進一步查看這些資源的索引出處;如果爲0,則可以通過UnloadUnusedAssets或UnloadAsset來將其從內存中去除。

資源管理

Q10:請問這個GameObject.Active的開銷怎麼這麼高?Activate會產生堆內存分配嗎?
請輸入圖片描述

這個是PC上的鼠標交互事件造成的,是UI界面的Active操作,所以觸發了各種相關的OnEnable調用,研發團隊可以在Profiler中進行進一步定位,查看根源。

一般來說,GameObject的Activate操作本身是不會產生堆內存分配,但它引發的各種底層類的OnEnable會產生堆內存的分配。開發團隊可以參考這裏加深理解:
http://blog.uwa4d.com/archives/Simple_PA_NGUI.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章