Unity3D 效能優化之Draw Call

2021-06-09 11:54:03 字數 1556 閱讀 1157

unity(或者說基本所有圖形引擎)生成一幀畫面的處理過程大致可以這樣簡化描述:引擎首先經過簡單的可見性測試,確定攝像機可以看到的物體,然後把這些物體的頂點(包括本地位置、法線、uv等),索引(頂點如何組成三角形),變換(就是物體的位置、旋轉、縮放、以及攝像機位置等),相關光源,紋理,渲染方式(由材質/shader決定)等資料準備好,然後通知圖形api——或者就簡單地看作是通知gpu——開始繪製,gpu基於這些資料,經過一系列運算,在螢幕上畫出成千上萬的三角形,最終構成一幅影象。

在unity中,每次引擎準備資料並通知gpu的過程稱為一次draw call。這一過程是逐個物體進行的,對於每個物體,不只gpu的渲染,引擎重新設定材質/shader也是一項非常耗時的操作。因此每幀的draw call次數是一項非常重要的效能指標,對於ios來說應盡量控制在20次以內,這個值可以在編輯器的statistic視窗看到。

unity內建了draw call batching技術,從名字就可以看出,它的主要目標就是在一次draw call中批量處理多個物體。只要物體的變換和材質相同,gpu就可以按完全相同的方式進行處理,即可以把它們放在乙個draw call中。draw call batching技術的核心就是在可見性測試之後,檢查所有要繪製的物體的材質,把相同材質的分為一組(乙個batch),然後把它們組合成乙個物體(統一變換),這樣就可以在乙個draw call中處理多個物體了(實際上是組合後的乙個物體)。

但draw call batching存在乙個缺陷,就是它需要把乙個batch中的所有物體組合到一起,相當於建立了乙個與這些物體加起來一樣大的物體,與此同時就需要分配相應大小的記憶體。這不僅會消耗更多記憶體,還需要消耗cpu時間。特別是對於移動的物體,每一幀都得重新進行組合,這就需要進行一些權衡,否則得不償失。但對於靜止不動的物體來說,只需要進行一次組合,之後就可以一直使用,效率要高得多。

unity提供了dynamic batching和static batching兩種方式。dynamic batching是完全自動進行的,不需要也無法進行任何干預,對於頂點數在300以內的可移動物體,只要使用相同的材質,就會組成batch。static batching則需要把靜止的物體標記為static,然後無論大小,都會組成batch。如前文所說,static batching顯然比dynamic batching要高效得多,於是,static batching功能是收費的……

要有效利用draw call batching,首先是儘量減少場景中使用的材質數量,即盡量共享材質,對於僅紋理不同的材質可以把紋理組合到一張更大的紋理中(稱為texture atlasing)。然後是把不會移動的物體標記為static。此外還可以通過combinechildren指令碼(standard assets/scripts/unity scripts/combinechildren)手動把物體組合在一起,但這個指令碼會影響可見性測試,因為組合在一起的物體始終會被看作乙個物體,從而會增加gpu要處理的幾何體數量,因此要小心使用。

對於複雜的靜態場景,還可以考慮自行設計遮擋剔除演算法,減少可見的物體數量同時也可以減少draw call。

總之,理解draw call和draw call batching原理,根據場景特點設計相應的方案來儘量減少draw call次數才是王道,其它方面亦然。

Unity3D 效能優化

unity3d 效能優化 一 程式方面 01 務必刪除指令碼中為空或不需要的預設方法 02 只在乙個指令碼中使用ongui方法 03 避免在ongui中對變數 方法進行更新 賦值,輸出變數建議在update內 04 同一指令碼中頻繁使用的變數建議宣告其為全域性變數,指令碼之間頻繁呼叫的變數或方法建議...

Unity3D效能優化總結

一 程式方面 01 務必刪除指令碼中為空或不需要的預設方法 02 只在乙個指令碼中使用ongui方法 03 避免在ongui中對變數 方法進行更新 賦值,輸出變數建議在update內 04 同一指令碼中頻繁使用的變數建議宣告其為全域性變數,指令碼之間頻繁呼叫的變數或方法建議宣告為全域性靜態變數或方法...

Unity 3D 效能優化總結

記憶體優化篇 cpu優化篇 unity中的優化技術 unity 3d ugui效能優化 unity 3d 優化記憶體 unity 3d mipmap unity 3d lod unity 3d 遊戲開發紋理壓縮方案 其他 效能優化 不要去頻繁getcomponent,獲取一次以後快取起來 優先使用a...