版本:2.4.3
參考:
Cocos Creator 性能優化:DrawCall(全面!)
主要是看論壇水友陳皮皮的文章《Cocos Creator 性能優化:DrawCall》,實際測試下drawcall。
一 碎圖+動態合圖測試
二 碎圖+AABB+ABAB測試
三 自動合圖測試(Auto Atlas)
四 系統字體文本測試
五 BMFont文本測試
六 遇到問題
一 碎圖+動態合圖測試
使用4張碎圖,理論4碎圖+1調試信息文本 = 5 drawcall,但是實際測試drawcall是2。
這是因為web默認開啟了動態合圖。動態合圖會額外占用內存,不同平台內存占用不一樣。
web平台默認開啟動態合圖。
小游戲和原生平台默認關閉動態合圖。
現在禁用動態合圖,代碼需要寫在項目腳本中的最外層,不要在start或onLoad中禁用,確保在項目加載過程中即時生效。否則如果在部分貼圖緩存已經釋放的情況下才啟用動態圖集,可能會導致報錯。
const {ccclass, property} = cc._decorator; //是否在將貼圖上傳至 GPU 之后刪除原始圖片緩存,刪除之后圖片將無法進行 動態合圖。 //web平台不需要開啟,因為web平台Image占用內存小。 //小游戲平台默認開啟,避免內存占用過高。 cc.macro.CLEANUP_IMAGE_CACHE = true; //禁用動態合圖 cc.dynamicAtlasManager.enabled = false; @ccclass export default class Helloworld extends cc.Component { start(){ console.log(cc.macro.CLEANUP_IMAGE_CACHE, cc.dynamicAtlasManager.enabled); //true, false } }
關閉動態合圖后,可以看到4碎圖+1調試信息 = 5 drawcall。
1. 動態合圖出現,是因為項目過大貼圖過多,導致很難使用靜態合圖Auto Atlas將圖片合並到一個圖集上。
2.動態合圖會占用內存,在小游戲和原生平台默認關閉。
3.動態合圖最大張數5張,使用完會重建,單張合圖最大2048*2048。
4.如果一直不切換場景,那么隨着動態合圖的數量增長,渲染效率可能會降低,適得其反。
5.動態合圖不用,記得剔除“Dynamic Atlas”模塊以減小引擎包體。
二 碎圖+AABB+ABAB測試
AABB:來自同一張圖的UI並列排放,drawcall仍然按1個算。
2個icon_001 + 2個icon_002 + 1調試信息 = 3 drawcall
ABAB:交叉的排放,drawcall會增加。
2個icon_001 + 2個icon_002 + 1調試信息 = 5 drawcall
總結:
所以來自同一圖集的UI,盡量並列排放,可以減少drawcall。
三 自動合圖測試(Auto Atlas)
靜態合圖可以使用TexturePacker或者AutoAtlas。
因為TexturePacker比較麻煩,每次美術增加或修改了UI,你得再用軟件去合圖一次, 所以還是直接使用AutoAtlas。
自動合圖需要構建時才會生效,平時調試時不會生效的。
總結:
使用AutoAtlas。
四 系統字體文本測試
1 系統字體文本打斷渲染合批
如果添加系統字體文本label,則會打斷合並批次提交。
2 icon_001 + 1調試信息 + 1文本 = 4 drawcall
2 文本三種緩存模式
NONE:
沒有任何操作,3個文本會打斷icon渲染合批,並且3個文本算3個drawcall。
2icon_001 + 3文本 + 1調試信息 = 6 drawcall
BITMAP:
如果關閉動態合圖,則這一項沒用。依然是
2icon_001 + 3文本 + 1調試信息 = 6 drawcall。
如果開啟動態合圖,則icon和文本會合並,2個icon和3個文本相當於1個drawcall。
2icon_001 + 3文本 + 1調試信息 = 2 drawcall
CHAR:
共享位圖的最大尺寸為 2048*2048,占滿了之后就沒辦法再渲染新的字符,需要切換場景才會清除共享位圖。
和動態合圖無關,字符會緩存到一張圖上,所以3個文本相當於1個drawcall。
2icon_001 + 3文本 + 1調試信息 = 4 drawcall
總結:
普通界面,關閉動態合圖情況下,選擇CHAR模式,並將文本並列排放,則能減少drawcall。
五 BMFont文本測試
1. BMFont會打斷渲染合批
2icon_001 + 2BMFont + 1調試信息 = 5 drawcall
2. BMFont沒有緩存模式,可以參與Auto Atlas靜態合圖。
將BMFont的圖片和icon圖標一起靜態合圖
2 icon + 2 BMFont + 1 調試信息 = 2 drawcall
總結:
大部分BMFont基本都是通用型,可能貫穿游戲很多個界面,所以合圖並到某個界面不合適。
在關閉動態合圖的情況下,和系統字體CHAR模式類似,只能相鄰排放來減少drawcall。
六 遇到問題
1 顯示動態合圖的調試信息問題
使用cc.dynamicAtlasManager.showDebug(true)可以顯示動態合圖調試信息,會將動態合圖展示在場景上的一個scrollView中。
代碼寫在onLoad里或者場景中沒有cc.Label,則啥也看不見。
一定要在場景中放一個cc.Label,設置cacheMode為Bitmap,然后在start里移動合圖的node的x和y,才能看得見動態合圖。
let node: cc.Node = cc.dynamicAtlasManager.showDebug(true); node.x = 1000; node.y = 0; console.log(node.x, node.y, node.width, node.height);
2 使用TexturePacker的合圖能參與動態合圖嗎
能
這是一個texturepacker的合圖
這是cc.dynamicAtlasManager.showDebug(true)后顯示的調試信息,可以看到texturepacker的合圖參與了動態合圖。
3 使用autoaltas自動合圖能參與動態合圖嗎
能
這是autoaltas的自動合圖
將劍擺到場景上,cc.dynamicAtlasManager.showDebug(true)顯示的調試信息,可以看到autoaltas的劍能參與動態合圖。
4 骨骼動畫能不能參與動態合圖
不能
擺一個骨骼動畫到場景中
cc.dynamicAtlasManager.showDebug(true)顯示的調試信息,可以看到骨骼動畫並沒有參與動態合圖。