DrawInstance和完全不做合批情況下的性能差異

1)DrawInstance和完全不做合批情況下的性能差異
​2)UWA報告中檢測出工程沒有的資源
3)精靈設置九宮後,如何不在界面中顯示出來
4)關於AssetBundle資源的卸載問題
5)Total Mono突然上漲的原因




這是第236篇UWA技術知識分享的推送。今天我們繼續爲大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。

UWA 問答社區:answer.uwa4d.com
UWA QQ羣2:793972859(原羣已滿員)

Rendering

Q:我做了個測試,環境:Unity 2019.4.15 ,機型:小米5X,繪製1000個物體(頂點數>300,不動態合批),測試順序是:Unity默認渲染(20 FPS)–>Update中通過Graphics.DrawInstance(16.5 FPS)–>通過CommandBuffer實現的DrawInstance(21.5 FPS),對於第二個測試DrawInstance性能反而降低了不太理解,有大佬幫忙解答嗎?

圖片和測試工程可通過以下鏈接下載:
鏈接:https://share.weiyun.com/ZFOlW1of
密碼:ip37rr

A:1.Instancing耗時更高主要原因還是GPU壓力比較大,見下面的測試案例:

測試1:1000個物體(頂點數88,關閉動態合批)

Default:子線程Camera.Render(14.59 ms)、Gfx.PresentFrame(3.94 ms)

Instancing:子線程Camera.Render(7.1 ms)、Gfx.PresentFrame(4.70 ms)

測試2:1000個物體(頂點數1278)

Default:子線程Camera.Render(15.02 ms)、Gfx.PresentFrame(9.01 ms)

Instancing:子線程Camera.Render(8.21 ms)、Gfx.PresentFrame(19.15 ms)

Instancing是能夠明顯降低CPU渲染(Camera.Render)耗時的,但GPU調用DrawInstanced()比Draw()的性能似乎差一些,導致CPU端等待耗時較高。所以Instancing總體幀率有所下降主要是GPU的壓力較大導致的。

2.如下圖Graphics.DrawMeshInstanced在Update中每幀調用存在腳本耗時明顯DrawInstancing更高(在Update中準備相關DrawInstance參數),Demo渲染的是靜態物體,使用CommandBuffer實現DrawInstancing可優化這部分耗時,同時在Update中的邏輯也會有New XXX[]數組這樣的Mono堆內存頻繁的分配,也會有GC影響(這部分影響較小)。

結論:Instancing可以降低CPU渲染耗時,但GPU API性能會有所降低,幀耗時還是受到CPU渲染耗時及GPU耗時的綜合影響,不同的機型可能表現的會有所差異。

Instancing的使用:推薦繪製大量靜態物體時使用CommandBuffer的實現,例如草海之類的。

感謝羽飛@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/60095ef310a17c6c2b09dc04


Texture

Q:請問一下:性能報告中,RGBA32的圖片有一些在工程中沒有,但是在報告中卻體現,請教一下這些是哪裏產生的?

 

A:截圖中的Background、UIMask、UISprite是由UGUI中默認的UI元素引入的,如下圖中的ScrollView:

 

 

UnityNormalMap這個是由於Shader中的紋理使用Bump作爲默認的值,但是在材質球中又沒有給這個紋理賦值導致的。對於這種空紋理的資源,在UWA本地資源檢測中是可以檢測出來的。

 

感謝Xuan@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/600a812910a17c6c2b09dc31


UGUI

Q:導入一張171*41的圖片,設置完九宮信息後創建UI圖片。然後設置圖片寬高爲0,並設置圖片模式爲Sliced。但是還是能看到圖片顯示出來了。個人感覺上是UV計算錯誤了。如果切換到Simple則圖片正常不顯示。請問大佬這是什麼原理?

測試工程可在原問答下載(版本:Unity 2018.4.23)

A:這個和九宮格圖片的實現原理有關,可以看看下面這個圖片:

當你選擇Sliced模式,他有一個最小的繪製區域,也就是四個角:1、3、7和9,必須繪製出來。當你設置的Rect大於1、3、7、9四個角組成的區域時,那麼2和8則是在x方向進行縮放,y方向不變,而4和6則是在y方向縮放,x方向不變;而5則是x和y方向都會進行縮放。當你選擇Simple模式,則是根據你設置的Rect範圍決定的,如果Rect比原始尺寸大,那麼就拉伸,反之則縮小;這也就是你可以不顯示的原因。

感謝李星@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/60096dcc10a17c6c2b09dc0d


AssetBundle

Q1:公共資源public.ab做全局預加載,常駐內存。某特定資源A引用了public.ab裏的一張大圖紋理,以及另外一個a.ab裏的資源。在沒加載A時,public.ab即使常駐內存也不會實際將那張大圖紋理實例化。

現在的問題是,當加載並用完A資源後,想把A徹底從內存中清理出去時,對a.ab進行Unload(true)可以把a.ab清理掉,但是public.ab裏的那張大圖,在不對public.ab進行Unload(true)的前提下,是沒有任何其它辦法能將它從內存中清掉嗎?

A1:如果能拿到那張Texture的引用,可以嘗試使用Resources.UnloadAsset

但個人認爲既然是公共資源,說明有可能被很多地方引用到,應做好public.ab裏面的資源都常駐內存的內存預算準備。否則,按照你例子中的說法,可能把這張大紋理單獨拿出來會好一些。

感謝範君@UWA問答社區提供了回答

Q2:由於該大圖紋理被多個UI預置體引用,因此放到了public.ab裏,但這些UI預置體,在遊戲大部分時間(比如掛機戰鬥時)不會打開,因此也是不需要用到的,故而想卸載。看來還是隻能再拆分出一類不常駐內存的公共資源,來解決這類問題了?

A2:既然要作爲公共資源,常駐內存,那麼就是從App的開始到App的結束都是不會去卸載的。如果你想原來在公共資源裏的小圖只有特定場景下才會使用到,平時不用時想卸載,可以參考下這個運行時動態圖集,動態將小圖合併到常駐內存的圖集中,不用時在動態剔除回收。

《Unity運行時動態圖集的實現》

感謝Coyote@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/6007ee4010a17c6c2b09db6f


Mono

Q:現象:在Total Mono突然撐大的那幾幀中,Used Mono並沒有上漲,如圖:

 

 

Used在50MB左右時,Total突然分配到140MB,這是爲什麼?

A:很有可能是一幀中分配了大量的堆內存,將Total撐大了,但本身的堆內存是可以GC掉的,所以Used並沒有太大的變化。

該問答由UWA提供,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/6007f1b810a17c6c2b09db70

封面圖來自網絡


今天的分享就到這裏。當然,生有涯而知無涯。在漫漫的開發週期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上準備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ羣:793972859(原羣已滿員)



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