大家好,我是曉衡!
上周我花了3天的時(shí)間,體驗(yàn)測(cè)試了一款 Creator 3.x 性能優(yōu)化工具:98K動(dòng)態(tài)分層合批。
它能將 DrawCall
超過(guò) 1000+ 次的 2D 界面,實(shí)現(xiàn)運(yùn)行時(shí)節(jié)點(diǎn)分層排序,利用引擎動(dòng)態(tài)合圖 + 批量渲染能力,從底層將 DrawCall 優(yōu)化到個(gè)數(shù)位。
測(cè)試案例是一個(gè) 2D 背包界面,我在 ScrollView 中動(dòng)態(tài)創(chuàng)建了 500 個(gè) item 元素。你可以看到,開啟合批優(yōu)化后 DrawCall 從 1016 直接降到了 8,游戲幀率也從 5 幀直接拉滿到 60 幀。
這里是H5測(cè)試體驗(yàn)鏈接,你也可以試一下:
98K動(dòng)態(tài)分層合批
支持H5、小游戲、原生等多個(gè)平臺(tái),而我的測(cè)試目標(biāo)是,觀察對(duì)比在不同平臺(tái)環(huán)境上,使用 98K 優(yōu)化前后的性能表現(xiàn)差異。
01 合批優(yōu)化測(cè)試對(duì)比
先給出我的測(cè)試結(jié)果,一共測(cè)試了 7 個(gè)環(huán)境:
- Mac M1 Chrome 桌面瀏覽器
-
realme X50 Pro Android 原生
- realme X50 Pro Android 微信小游戲
- OPPO R11s Plus Android 原生
- OPPO R11s Plus Android 微信小游戲
- iPhone11 微信小游戲
- iPhone7 微信瀏覽器
以上測(cè)試環(huán)境數(shù)據(jù),我整理了個(gè)表格,方便大家對(duì)比優(yōu)化關(guān)后的效果:
如果你覺得看數(shù)據(jù)表還是很費(fèi)勁的話,可以直接看曉衡這個(gè)結(jié)論:
- 開啟合批優(yōu)化后,所有平臺(tái)都能跑到 60 幀,ScrollView列表滑動(dòng)流暢;
- 除減少 DrawCall 外,還啟了渲染剔除,降低了渲染面數(shù);
- 優(yōu)化前后差異對(duì)比是:桌面 > 低端原生 > 低端小游戲 > 中高端原生&小游戲。
桌面瀏覽器上的優(yōu)化性能最佳,這是我萬(wàn)萬(wàn)沒想到的,不論是 Mac 還是 Windows 系統(tǒng),都是如此。未合批前僅僅只有 5 幀,在列表上滑動(dòng),非常卡頓,基本上無(wú)法使用。開啟合批后,直接拉滿到60幀,列表滑動(dòng)流暢。
其次是在 iPhone 上,小游戲上的優(yōu)化比瀏覽器要好,未合批前不到 30 幀,開啟合批后滿幀 60,列表滑動(dòng)也更順滑。
然后是在 Android 手機(jī)上,中高機(jī)型未合批前就能達(dá)到 50 ~ 60 幀,優(yōu)化后提升不到 10 幀的樣子,不看調(diào)試數(shù)值感覺不明顯。低端機(jī)型的優(yōu)化效果不錯(cuò),有 20 ~ 30 幀的提升,硬件性能越低優(yōu)化后的效果越好。
最后,我在多說(shuō)一點(diǎn),就是在 iPhone 和 Android 低配機(jī)型上,原生性能要低于H5和小游戲,優(yōu)化效果會(huì)好。下面是我構(gòu)建的 APK 安裝包,感興趣的伙伴可以來(lái)體驗(yàn)一下:
- 鏈接: https://pan.baidu.com/s/12aEvOL9fQrpyB4Xs--OALg?pwd=4znt 提取碼: 4znt
測(cè)試數(shù)據(jù)和結(jié)論有了,我們?cè)偕钊胍稽c(diǎn),98K動(dòng)態(tài)分層合批的核心是對(duì) DrawCall 的優(yōu)化,初學(xué)游戲開發(fā)的小伙伴,可能會(huì)有疑問:
DrawCall 是什么?為什么減少 DrawCall 能提升游戲的性能?合批又是個(gè)什么鬼?
而有過(guò)游戲開發(fā)經(jīng)驗(yàn),又愛思考的老鐵多半會(huì)問:
道具背包這類應(yīng)用場(chǎng)景,一個(gè) item 混合有復(fù)雜的圖片、文字,98K是如何避免 DrawCall 被打斷的?
下面我就來(lái)嘗試一下,能否將上面幾個(gè)問題說(shuō)清楚,你可以更加清楚知道是否適合在自己的項(xiàng)目中使用98K合批優(yōu)化。
02 理解Drawcall與合批
DrawCall 是什么?
- 簡(jiǎn)單來(lái)講 CPU 準(zhǔn)備好渲染數(shù)據(jù),提交給 GPU 進(jìn)行繪制的這個(gè)過(guò)程就是一次 DrawCall
為什么減少 DrawCall 能提升游戲的性能?
- GPU 渲染圖像的速度非常非常快;
- CPU 的內(nèi)存\顯存讀寫、數(shù)據(jù)處理和渲染狀態(tài)切換,相比 GPU 非常非常慢;
- 大量的 DrawCall 會(huì)讓 CPU 忙到焦頭爛額,而 GPU 大部分時(shí)間都在摸魚
因此,盡可能一次性將更多的渲染數(shù)據(jù)提交給 GPU,減少 CPU 的工作時(shí)間,從而提升游戲性能。
什么是合批?
- 簡(jiǎn)單來(lái)說(shuō),組織更多渲染數(shù)據(jù)提交給 GPU 的過(guò)程,稱之為“批量渲染”簡(jiǎn)稱“合批”
- 但要實(shí)現(xiàn)合批的前提是:渲染數(shù)據(jù)必須一致
更多關(guān)于 DrawCall 優(yōu)化的理解,可以閱讀陳皮皮的這篇文章:Cocos Creator 性能優(yōu)化:DrawCall
舉個(gè)例子
比如像下面這樣的節(jié)點(diǎn)樹結(jié)構(gòu),就無(wú)法實(shí)現(xiàn)合批:
因?yàn)?item 節(jié)點(diǎn)下的 Sprite 與 Label 節(jié)點(diǎn)渲染類型不同,并相互間隔排列,引擎無(wú)法向 GPU 批量提交渲染數(shù)據(jù)。
因此渲染一個(gè) item 需要 DrawCall 4次:Sprite → Label → Sprite → Label。
我們調(diào)整一下 item 下的節(jié)點(diǎn)順序,像下面這樣:
試試你能計(jì)算出上圖中的 DrawCall 值嗎?在 Creator 引擎中預(yù)覽運(yùn)行游戲,在畫面左下角,你會(huì)看到 DrawCall 的值顯示為 3。
細(xì)心的你這時(shí)可能會(huì)問:為什么 DrawCall 是 3 而不是 2 呢?
不用懷疑,你計(jì)算的 DrawCall 為 2 是正確的,因?yàn)橐孢@里會(huì)占用一次 DrawCcall,具體為什么,我們后面來(lái)說(shuō)原因,你也可以思考一下!
03 98K是如何避免 DrawCall 被打斷?
要想避免 DrawCall 被打斷,首先要理解什么是 DrawCall 打斷!
通過(guò)上面的舉例,不知道你沒有點(diǎn)感覺了。我們?cè)賮?lái)看多個(gè) item 節(jié)點(diǎn)樹 DrawCall 情況又會(huì)是怎么樣的呢?
在層級(jí)管理器中,我們?cè)購(gòu)?fù)制一顆 item 節(jié)點(diǎn)樹出來(lái),見下圖所示:
從上圖可以看出,兩顆 item 節(jié)點(diǎn)樹時(shí)又出現(xiàn):item1(Sprite → Label) → item2(Sprite → Label) 交替的情況,合批就這樣被打斷了。
聰明的我立馬會(huì)想到,將所有 item 下的節(jié)點(diǎn)合并不就好了,像下圖這樣:
效果是不是很好?6 個(gè)節(jié)點(diǎn)只有 2 次 DrawCall !就這樣干?
有經(jīng)驗(yàn)的你問題又來(lái)了,我們的邏輯代碼通常是以單個(gè) item 為單位建立的對(duì)象,如果將類型節(jié)點(diǎn)點(diǎn)合并到一起,上層邏輯代碼豈不是要亂成一鍋粥?
優(yōu)化的方法是知道了,但代價(jià)太大,不知道如何下手!
這個(gè)問題一直困擾我多年,一直沒找到可行的解決方案,直到遇到98K動(dòng)態(tài)合批的開發(fā)者。
這里不得不說(shuō)下 98K動(dòng)態(tài)合批 的強(qiáng)悍,就在于它可以讓你無(wú)視 item 子節(jié)點(diǎn)順序和層級(jí)關(guān)系,只需要在上層容器節(jié)點(diǎn)上添加 BatchItems
組件,最大程度上保證合批不被中斷,實(shí)現(xiàn)該節(jié)點(diǎn)樹的渲染優(yōu)化。
其代碼實(shí)現(xiàn)原理是:
- 攔截引擎渲染開始事件,對(duì)節(jié)點(diǎn)樹下的所有子節(jié)點(diǎn)按類型重新分層排序;
- 攔截引擎渲染結(jié)束事件,立即還原渲染前的節(jié)點(diǎn)樹排序,從而實(shí)現(xiàn)無(wú)入侵式的合批優(yōu)化
-
BatchItem
組件唯一的 Culling 屬性是可選的,它會(huì)拿 Culling 屬性所指定的矩形區(qū),與容器中 item 矩形做相交測(cè)試,將不在 Culling 區(qū)的元素從渲染隊(duì)列中剔除掉
05 應(yīng)用場(chǎng)景
需要注意的是98K合批優(yōu)化,僅適用于 2D UI 界面的優(yōu)化,特別是具有大量重復(fù)結(jié)構(gòu)的 item 場(chǎng)景如:背包系統(tǒng)、滑動(dòng)列表、技能欄、聊天界面等,以下應(yīng)用場(chǎng)景供大家參考。
背包系統(tǒng)
頻道列表
游戲排行榜
聊天界面
04 注意事項(xiàng)
我在使用 98K編寫前面那個(gè)背包測(cè)試工程時(shí),踩到幾個(gè)坑有幾點(diǎn)需要注意:
item 下子節(jié)點(diǎn)名字不能重復(fù)需保持唯一性
多個(gè)同結(jié)構(gòu)的 item 子節(jié)點(diǎn)名字需要保持一致
節(jié)點(diǎn)的 Layer 屬性需保持相同,建議統(tǒng)一為 UI_2D
-
需要手動(dòng)開啟引擎的動(dòng)態(tài)合圖和關(guān)閉清除圖片緩存開關(guān)
dynamicAtlasManager.enabled = true; macro.CLEANUP_IMAGE_CACHE = false;
充分使用引擎的動(dòng)態(tài)合圖,將盡量多的圖片合并,需要增大項(xiàng)目設(shè)置中 BATCHER2D_MEM_INCREMENT 宏的參數(shù)值
06 結(jié)語(yǔ)
最后,我再小結(jié)一下 98K動(dòng)態(tài)分層合批 的整體感受!
它是非常適用于像背包系統(tǒng)、滑動(dòng)列表、聊天消息這類 2D UI 場(chǎng)景。
如果因游戲中因節(jié)點(diǎn)太多導(dǎo)致圖文分層原因,打斷合批造成 DrawCall 劇增影響性能和增加發(fā)熱問題,98K合批可以說(shuō)是首選的優(yōu)化工具。
當(dāng)然,你也可以使用虛擬列表的技術(shù)并不用創(chuàng)建出所有的 item,但我的感受是98K更為簡(jiǎn)單粗暴、立桿見影,能結(jié)合使用效果更定會(huì)更佳。
而從多個(gè)環(huán)境平臺(tái)的測(cè)試效果來(lái)看:
- 桌面瀏覽效果最佳,如果你是做 H5 頁(yè)游,那再適合不過(guò)
- 再次是 iPhone 瀏覽器、小游戲優(yōu)化效果顯著
- 然后是中低端的 Android 也比較推薦
下面是 H5 | Android 測(cè)試鏈接,強(qiáng)烈建議你也來(lái)體驗(yàn)一下,歡迎留言說(shuō)說(shuō)在你的設(shè)備上體驗(yàn)感受。
H5測(cè)試鏈接:
- http://gameview.creator-star.cn/98K/batch-items/index.html
Android測(cè)試包下載
- 鏈接: https://pan.baidu.com/s/12aEvOL9fQrpyB4Xs--OALg?pwd=4znt 提取碼: 4znt
Cocos Store下載鏈接
- https://store.cocos.com/app/detail/4310
希望今天的分享能夠?qū)Υ蠹矣兴鶐椭蛦l(fā), 曉衡會(huì)繼續(xù)挖掘 Cocos Store 上的優(yōu)秀作品分享給大家,歡迎關(guān)注!