第一家,天神互動的題把,有這個,當時直接朦le~~(一個一年游戲開發小菜鳥)
一、什么是批處理?
我們知道Unity3D在屏幕上繪制一個圖形本質上調用OpneGL或者DirectX這樣的API,因此在這個過程中會產生一定程度上的性能消耗。DrawCall是OpenGL中描述繪制次數的一個量,例如一個基本的OpenGL繪制流程是設置顏色->繪圖方式->頂點坐標->繪制->結束,在繪制的過程中每幀都會重復這個過程,這就是一次DrawCall,所以當游戲中的繪制過程變得復雜的時候,就會帶來DrawCall的急劇增加,進而帶來游戲的性能問題,反映到游戲表現上就變成了優化問題。
那么在Unity3D中采取了什么樣的措施來降低DrawCall呢?這就是我們今天要說的批處理,換句話說Unity3D使用了批處理來達到降低DrawCall的目的,批處理希望通過對物體網格的重組來獲得更高的繪制效率,試想以下如果將多個物體合並為一個物體,那么在繪制的時候只需要繪制一次就夠了,因此從這個角度上來講這樣做肯定是可以降低DrawCall的,更深刻的一種理解是這里體現了一種資源循環調用的思想,接觸過android開發的朋友們一定知道ListView控件可以對其元素進行“緩存”從而提高效率,因為我們可以發現其實ListView是對列表項進行某種程度上的“復用”從而提高了效率,在Unity3D這里同樣遵循了這個原理。
在Unity3D中進行批處理的一個前提是相同材質的物體可以被合並,如果這些物體使用不同的材質,那么當我們把這些材質對應的紋理打成“圖集”以后可以對其進行合並,並且在合並的時候應該是用Renderer.sharedMaterial 而非 Renderer.material以保證材質是可以共享的。關於DrawCall的相關細節大家從這里來了解,博主並未對圖形學領域有過深入的研究,因此就不在這里班門弄斧了啊,哈哈!
二、Unity3D中批處理的兩種方式
在Unity3D中有靜態批處理和動態批處理兩種方式,下面我們就來分別說說這兩種不同的批處理方式!
靜態批處理
靜態批處理其實大家都是知道的。為什么這樣說呢?因為我們在使用Unity3D的過程中無形中培養了這樣一個習慣,那就是將場景中相對來說“靜態”的物體都勾選Static選項,這在Unity3D中稱為Static GameObjects,並且因為這一特性和Lightmapping、Navigation、Off-meshLinks、ReflectionProbe、Occluder and Occludee等內容均有着密切的聯系,因此說靜態批處理大家都是知道的其實一點都為過,和場景優化相關的內容博主會在后續的博客中涉及。
靜態批處理允許游戲引擎盡可能多的去降低繪制任意大小的物體所產生的DrawCall,它會占用更多的內存資源和更少的CPU資源,因為它需要額外的內存資源來存儲合並后的幾何結構,如果在靜態批處理之前,如果有幾個對象共享相同的幾何結構,那么將為每個對象創建一個幾何圖形,無論是在編輯器還是在運行時。這看起來是個艱難的選擇,你需要在內存性能和渲染性能間做出最為正確的選擇。
在內部,靜態批處理是通過將靜態對象轉換為世界空間,並為它們構建一個大的頂點+索引緩沖區。然后,在同一批中,一系列的“便宜”畫調用,一系列的“便宜”,幾乎沒有任何狀態變化之間的。所以在技術上它並不保存“三維的調用”,但它可以節省它們之間的狀態變化(這是昂貴的部分)。使用靜態批處理非常簡單啦,只要勾選物體的Static選項即可!
動態批處理
相對靜態批處理而言,動態批處理的要求更為嚴格一些,它要求批處理的動態對象具有一定的頂點,所以動態批處理只適用於包含小於900個頂點屬性的網格。
如果你的着色器使用頂點位置,法線和單光,然后你可以批處理300個頂點的動態對象;而如果你的着色器使用頂點位置,法線,uv0,UV1和切線,那么只能處理180個頂點的動態對象。接下來最為重要的一點,如果動態對象使用的是不同的材質,那么即使進行了動態批處理從效率上來講並不會有太大的提升。如果動態對象采用的是多維子材質,那么批處理是無效的。
如果動態對象接收實時光影,同樣批處理是無效的。點擊原文鏈接查看代碼~
這段腳本的核心是CombineMeshes()方法,該方法有三個參數,第一個參數是合並實例的數組,第二個參數是是否對子物體的網格進行合並,第三個參數是是否共享材質,如果希望物體共享材質則第三個參數為true,否則為false。
在我測試的過程中發現,如果選擇了對子物體的網格進行合並,那么每個子物體都不能再使用單獨的材質,默認會以第一個材質作為合並后物體的材質
那么批處理對游戲效率提升究竟有怎樣的作用呢?我們來看下面幾組測試對比:
1、三個不同的物體使用同一種材質,不做靜態批處理,不做動態批處理:DrawCall為4、面數為584、頂點數為641
2、三個不同的物體使用同一種材質,只做靜態批處理,不做動態批處理:DrawCall為2、面數為584、頂點數為641
3、三個不同的物體使用不同的材質,不做靜態批處理,不做動態批處理:DrawCall為4、面數為584、頂點數為641
4、三個不同的物體使用不同的材質,只做靜態批處理,不做動態批處理:DrawCall為4、面數為584、頂點數為641
5、三個不同的物體使用不同的材質,不做靜態批處理,只做動態批處理:DrawCall為4、面數為584、頂點數為641
6、三個不同的物體使用不同的材質,做靜態批處理,做動態批處理:DrawCall為4、面數為584、頂點數為641
7、三個不同的物體使用同一種材質,不做靜態批處理,只做動態批處理:DrawCall為4、面數為584、頂點數為641
1-如果不同的物體間共享材質,則可以直接通過靜態批處理降低DrawCall
2、動態批處理並不能降低DrawCall、面數和頂點數(我不會告訴你我昨天傻呵呵地合並了好多場景中的模型,結果面數和頂點數並沒有降下來,23333)
3、不管是靜態批處理還是動態批處理都會影響Culiing,這同樣是涉及到場景優化的一個概念;
來自——蠻牛秦元培