溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

U3D DrawCall優(yōu)化手記

發(fā)布時間:2020-07-21 01:51:44 來源:網(wǎng)絡(luò) 閱讀:245 作者:wyb10a10 欄目:開發(fā)技術(shù)

在最近,使用U3D開發(fā)的游戲核心部分功能即將完成,中間由于各種歷史原因,導致項目存在比較大的問題,這些問題在最后,恐怕只能通過一次徹底的重構(gòu)來解決

現(xiàn)在的游戲跑起來會有接近130-170個左右的DrawCall,游戲運行起來明顯感覺到卡,而經(jīng)過一天的優(yōu)化,DrawCall成功縮減到30-70個,這個效果是非常顯著的,并且這個優(yōu)化并沒有通過將現(xiàn)有的資源打包圖集來實現(xiàn),圖集都是原有的圖集,如果從全局的角度對圖集再進行一次優(yōu)化,那么DrawCall還可以再減少十幾個

本次優(yōu)化的重點包括:層級關(guān)系和特效

對于U3D,我是一個菜鳥,對于U3D的一些東西是一知半解,例如DrawCall,我得到的是一些并不完全正確的信息,例如將N個紋理打包成一個圖集,這個圖集就只會產(chǎn)生一個DrawCall,如果不打成圖集,那么就會有N個DrawCall,這個觀點在很多人的認識里都是正確的,因為可以通過簡單的操作來驗證,但嚴格來說,這個觀點是錯誤的,因為它還受層級關(guān)系影響!

渲染順序

U3D的渲染是有順序的,U3D的渲染順序是由我們控制的,控制好U3D的渲染順序,你才能控制好DrawCall

一個DrawCall,表示U3D使用這個材質(zhì)/紋理,來進行一次渲染,那么這次渲染假設(shè)有3個對象,那么當3個對象都使用這一個材質(zhì)/紋理的時候,就會產(chǎn)生一次DrawCall,可以理解為一次將紋理輸送到屏幕上的過程,(實際上引擎大多會使用如雙緩沖,緩存這類的手段來優(yōu)化這個過程,但在這里我們只需要這樣子認識就可以了),假設(shè)3個對象使用不同的材質(zhì)/紋理,那么無疑會產(chǎn)生3個DrawCall

接下來我們的3個對象使用2個材質(zhì),A和B使用材質(zhì)1,C使用材質(zhì)2,這時候來看,應(yīng)該是有2個DrawCall,或者3個DrawCall。應(yīng)該是2個DrawCall啊,為什么會有3個DrawCall???而且是有時候2個,有時候3個。我們按照上面的DrawCall分析流程來分析一下:

1.渲染A,使用材質(zhì)1
2.渲染B,使用材質(zhì)1
3.渲染C,使用材質(zhì)2

在這種情況下是2個DrawCall,在下面這種情況下,則是3個DrawCall

1.渲染A,使用材質(zhì)1
2.渲染C,使用材質(zhì)2
3.渲染B,使用材質(zhì)1

因為我們沒有控制好渲染順序(或者說沒有去特意控制),所以導致了額外的DrawCall,因為A和B不是一次性渲染完的,而是被C打斷了,所以導致材質(zhì)1被分為兩次渲染

那么是什么在控制這個渲染順序呢?首先在多個相機的情況下,U3D會根據(jù)相機的深度順序進行渲染,在每個相機中,它會根據(jù)你距離相機的距離,由遠到近進行渲染,在UI相機中,還會根據(jù)你UI對象的深度進行渲染

那么我們要做的就是,對要渲染的對象進行一次規(guī)劃,正確地排列好它們,規(guī)則是,按照Z軸或者深度,對空間進行劃分,然后確定好每個對象的Z軸和深度,讓使用同一個材質(zhì)的東西,盡量保持在這個空間內(nèi),不要讓其他材質(zhì)的對象進入這個空間,否則就會打斷這個空間的渲染順序

在這個基礎(chǔ)上,更細的規(guī)則有:

  • 場景中的東西,我們使用Z軸來進行空間的劃分,例如背景層,特效層1,人物層,特效層2

  • NGUI中的東西,我們統(tǒng)一使用Depth來進行空間的劃分

  • 人物模型,當人物模型只是用一個材質(zhì),DrawCall只有1,但是用了2個以上的材質(zhì),DrawCall就會暴增(或許對材質(zhì)的RenderQueue進行規(guī)劃也可以使DrawCall只有2個,但這個要拆分好才行),3D人物處于復雜3D場景中的時候,我們的空間規(guī)則難免被破壞,這只能在設(shè)計的時候盡量去避免這種情況了

  • 使用了多個材質(zhì)的特效,在動畫的過程中,往往會引起DrawCall的波動,在視覺效果可以接受的范圍內(nèi),可以將特效也進行空間劃分,假設(shè)這個特效是2D顯示,那么可以使用Z軸來劃分空間

打包圖集

每個材質(zhì)/紋理的渲染一定是會產(chǎn)生DrawCall的,這個DrawCall只能通過打包圖集來進行優(yōu)化

制作圖集一般遵循幾個規(guī)則:

  • 從功能角度進行劃分,例如UI可以劃分為公共部分,以及每個具體的界面,功能上,顯示上密切相關(guān)的圖片打包到一起

  • 不要一股腦把所有東西打包到一個圖集里,特別是那些不可能同時出現(xiàn)的東西,它們就不應(yīng)該在一個圖集里,這樣的圖集意義不大,減少不了DrawCall,并且一個你不需要顯示的圖片,會一直占用你的內(nèi)存,這讓我非常不爽

  • 注意控制圖集的大小,不要讓圖集太大,一個超級大圖集的DrawCall消耗或許頂?shù)纳鲜畮讉€小圖集的消耗

字符圖集,在使用BMFont或者其他工具生成圖片字的時候,我們往往是直接導入一大串文字,然后直接生成圖片,但實際上這上面的操作也有優(yōu)化空間,例如BMFont生成的圖片大小,是可以設(shè)置的,有兩個規(guī)則,一個規(guī)則是導出的圖片盡量小,另一個是導出的圖片盡量少,默認的大小應(yīng)該是512x512,假設(shè)你生成的圖片256x256就可以容納,那么多做一個操作你可以節(jié)省這么多空間,另外當你輸入多幾個字,就導致增加一張圖片時,例如1024變成2048,那么你可以考慮使用3張512的圖片,這樣也會節(jié)省空間

經(jīng)過精心劃分的圖集在加上精心規(guī)劃的渲染順序,DrawCall會有一個質(zhì)的優(yōu)化

特效清理

U3D提供了非常便捷的方法讓我們很輕易地使用美術(shù)給過來的特效,懶惰的U3D程序猿會直接放入U3D,甚至不去看這是個什么特效,我們的特效一般都是一瞬間的事情,例如技能特效,或者其他什么特效,那么特效播放完,這個特效我們就看不到了,但假設(shè)這個特效在播放結(jié)束的時候,沒有將自身的Active屬性設(shè)置為false,那么它就會繼續(xù)占用你的DrawCall,消耗你設(shè)備的計算能力,所以程序需要保證當一個特效播放完之后,能夠被消耗,或者設(shè)置為非激活的狀態(tài),可以使用一些公共方法來完成特效播放完之后的清理工作(自己實現(xiàn)2個靜態(tài)函數(shù),一個播放完銷毀,一個播放完設(shè)置未激活)

完成DrawCall的優(yōu)化之后,接下來就是內(nèi)存的優(yōu)化了,(內(nèi)存優(yōu)化手記 待續(xù))


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI