每日一句:別聽世俗耳語,看自己的風景就好
目錄
SA的原理:
SA的優點:
SA的缺點:
DrawCall是什么?
批處理是什么?
我們先了解一下UGUI系統的運行原理吧!
提到圖集優化,我想先引出一個經典的游戲優化案例:
《超級馬里奧》的Tile壓縮方法:
由于紅白機的性能相比現在的家用主機來說極為有限,無論是儲存器性能還是處理器性能,所以當時的開發者采用“Tile瓦片”(每個瓦片8X8像素大小)作為基本的圖片存儲單元,然后再把這些瓦片拼接在一起。
如此以來畫面分辨率256X240的紅白機用8X8瓦片來填滿只需要32 * 30 = 960張瓦片,給每個瓦片一個0至255的編號,那么最多只需要960B來表示一個屏幕里的所有圖片,并且瓦片的內容是重復的并且個數是有限的,所要求的存儲性能以及內存性能都因此大大降低。
當然為了極致的性能壓縮性能,那個時代的開發者也應用了不少的技巧:
1.一個角色的行走動畫,用一張圖片進行左右交替翻轉就能實現,減少了存儲壓力。
2.天上的云地上的草疊加放置,表現大小規模不同。
3.角色的圖片只存儲一半,用的時候再翻轉拼接,又進一步壓縮了存儲。
這些前人的智慧也對主流的游戲引擎有著深遠影響:Sprite Atlas(精靈圖集,以下統稱SA)
不僅僅局限于以上描述的方面,SA甚至可以應用于2D 和 3D 項目中的 UI、粒子系統、貼圖等等。
現在我們對SA進行一個詳細的歸納總結:
SA的原理:
是一種將多張小圖匯總,打包成為一個大圖的技術。在游戲運行時只需要載入一張大圖到內存便可以實現多個素材的載入,是一種優化性能的手段,減少多次DrawCall對性能的占用。
SA的優點:
將多個圖片合并到一張大圖中,減少多次DrawCall對性能的占用。
SA的缺點:
當不經常使用的素材被放到圖集中時,即使改素材不被使用也會被載入內存,浪費了內存資源;并且圖集的大小固定為長邊的二次冪,如果圖集內素材的大小差距過大,會直接造成儲存的浪費。
前期要求:
首先我們先找到PackageManager,在Unity Registry中下載2D包。不然無法在項目中創建SA內容。
點擊“install”,下載這個包
然后找到Project Setting選項>Editor>Sprite Atlas>Mode
Mode默認是Disabled,更改為Always Enabled,V1和V2兩個版本目前沒有很大的區別,選V1就行
其他兩個選項的意思是:Enabled For Builds——在項目導出后應用圖集,所以在編輯器里面看到的圖集仍然是原來的那些圖片。
為了保證項目能接近玩家原生感受選擇Always Enabled。
SA的創建:
項目內右鍵Project>2D>Sprite Atlas創建SA。
這里如果沒有前期準備的內容,就無法創建SA。
配置SA:
點擊我們新創建的SA
解釋一下該面板的幾個重要內容的意義:
- Include in Build:是否在游戲發布后構建到游戲中
- Allow Rotation:是否允許旋轉圖片,如果勾選,在構建圖集時可能會旋轉對應的圖片,建議禁用
- Tight Packing:選中可根據圖片的輪廓而非默認矩形輪廓來打包精靈,讓圖片排列更緊密,建議禁用,否則UI元素在顯示時可能會重疊顯示其他的圖片,因為在獲取對應Sprite時是按矩形輪廓來獲取的
- Padding:不同UI元素之間的間隔,單位為像素,避免圖片之間過近導致顯示出問題
- Objects for Packing:需要打包的UI元素,可以放文件夾或者單個圖片,放文件夾可以將文件夾所有的圖片打包進這個圖集中,圖片的格式需要設置為Sprite(2D and UI),一個圖集最大的尺寸是2048*2048
以上為SA的使用方法以及原理,當然還有其他的圖集系統類似于Texture Atlas的內容,不過原理上也大同小異,下面我們深入的了解一下圖集優化的內容。
前文提到了DrawCall,這里解釋一下DrawCall的相關概念:
DrawCall是什么?
當我們在渲染一個物體時,需要通知GPU執行渲染的指令,這一過程叫做“DrawCall”。而調用DrawCall的次數越多,對GPU和CPU的性能開銷就越大,本身電腦的性能就有限,因此我們便要減少DrawCall的次數,減輕對GPU的性能負擔。所以開發者們就想到了上述類似Sprite Atlas的方法,以減少性能開銷。
批處理是什么?
上面我們了解了Sprite Atlas的運行原理,而批處理便是該原理的名稱;由于每一次DrawCall就可以大致理解為一個渲染批次(batch)。Draw call屬于資源密集型的指令,圖形API要為每個Draw call做大量的工作。造成CPU性能消耗的主要是渲染狀態的切換導致的,例如切換到不同的材質,這會導致在圖形驅動中產生密集的資源驗證和切換。為了減少draw call的調用,Unity引入了兩種優化技巧:
- 動態批處理:對于足夠小的mesh,動態批處理通過將他們的頂點整合到一個批次中進行繪制。
- 靜態批處理:通過將不會移動的靜態物體合并到更大的mesh中,以提升渲染速度。
材質方面的要求
只有使用了相同材質的物體才能夠實現批處理。如果兩個不同的物體,使用的兩個材質,只是紋理上的差別,那就把他們的紋理合并到一起,這樣就可以使用同一個材質。腳本中使用Render.material屬性時,會重新生成一個原來材質的拷貝,所以用Render.sharedMaterial可以保持材質的一致性(但是使用同一個材質的物體,都會被改變)。關于陰影,只要材質中使用的是相同的Shadow Pass,就可以實現批處理,即便他們不是同一個材質。
我們先了解一下UGUI系統的運行原理吧!
UGUI是在3D網格下建立起來的UI系統,它的每個元素都是通過3D模型網格的形式構建起來的。當UI系統被實例化時,首先要做的就是構建網格。【也就是說,Unity在制作一個圖元,或者一個按鈕,或者一個背景時,都會先構建一個方形網格,再將圖片放入網格中。可以理解為構建了一個3D模型,用一個網格綁定一個材質球,材質球里存放要顯示的圖片。】
那么這里有一個問題界面上成千上萬個元素就會擁有成千上萬個材質球、圖片。如果GPU對每個材質球和網格都進行渲染,將會導致GPU的負擔重大,怎么辦呢?
UGUI對這種情況進行了優化,它
- 將一部分相同類型的圖片集合起來合成一張圖,
- 然后將擁有相同圖片、相同著色器的材質球指向同一個材質球,
- 并且把分散開的模型網格合并起來,
- 這樣就生成幾個大網格和幾個不同圖集的材質球,
以及少許整張的圖集節省了很多材質球、圖片、網格的渲染,UI系統的效率提升了很多,游戲在進行時也順暢了許多。
這就是圖集概念,它把很多張圖片放置在一張圖集上,使得大量的圖片和材質球不需要重復繪制,只要改變模型頂點上的UV和顏色即可。
我們設想一下,如果每時每刻都在移動一個元素,那么UGUI系統就會不停地拆分合并網格,也就會不停地消耗CPU來使得畫面保持應有的樣子。這些合并和拆分的操作會消耗很多CPU,我們要盡一切可能節省CPU內存盡量把多余的CPU讓給核心邏輯。UGUI系統在制作完成后,性能優劣差距很多時候都會出現在這里。
我們要如何想方設法合并更多的元素,減少重構網格的次數,以達到更少的性能開銷目的呢?(UI優化)請閱讀這篇文章啦
Unity—UI-CSDN博客https://blog.csdn.net/m0_63330263/article/details/136473724?spm=1001.2014.3001.5501本文成果由CSDN博主“Lyrissss_”與我共同創作