Cocos Creator性能調(diào)優(yōu)優(yōu)化集錦

一、 為什么要做性能優(yōu)化?

性能:是一種優(yōu)秀的能力。喚醒快、運(yùn)行持久、穩(wěn)定

這種能力在游戲上能讓你的用戶感覺(jué)很,表征表現(xiàn)為加載快,手機(jī)不發(fā)熱,運(yùn)行流暢,不卡頓。所以,性能優(yōu)化的終極目標(biāo)是,讓你的用戶感覺(jué)很,當(dāng)然這種爽你不能以犧牲自己為代價(jià),要考慮成本和副作用(總不能頻繁使用偉哥對(duì)吧)。

我們要優(yōu)化性能,首先要搞明白是哪些因素會(huì)影響性能?是體力不行就得加強(qiáng)鍛煉,是操勞過(guò)度就應(yīng)該學(xué)會(huì)休息。點(diǎn)擊鏈接加入群聊【Unity/Cocos交流群】

在我們的游戲中,哪些因素會(huì)影響性能呢?

二、 影響性能的因素有哪些?

如果大家不知道如何分析,那我給大家引導(dǎo)下。

當(dāng)你玩游戲的時(shí)候,首先是不是要將你的游戲加載到內(nèi)存。前戲太長(zhǎng),你肯定會(huì)等得不耐煩吧,不爽,是不是要優(yōu)化。那么第一個(gè)問(wèn)題來(lái)了,如何優(yōu)化游戲加載速度(三、1),我們先記錄下來(lái),下面逐一講解。

其次,你好不容易把東西放內(nèi)存里去了,但是屏幕沒(méi)任何東西,也不給你發(fā)出點(diǎn)聲音。這體驗(yàn)不好!也就是說(shuō)屏幕渲染游戲界面耗時(shí)太長(zhǎng),卡頓,需要優(yōu)化,所以,第二個(gè)問(wèn)題,如何優(yōu)化渲染速度(三、2)

最后游戲運(yùn)行過(guò)程中,運(yùn)行速度受什么影響?與設(shè)備內(nèi)存、CPU、代碼有關(guān),所以我們要做內(nèi)存優(yōu)化(三、3)CPU占用及性能優(yōu)化(三、4)

三、 性能優(yōu)化從哪些方面著手?

1. 如何優(yōu)化游戲加載速度【加載優(yōu)化】

問(wèn)大家一個(gè)問(wèn)題,你一個(gè)8M的東西和人家一個(gè)1M的東西,你說(shuō)誰(shuí)會(huì)先加載進(jìn)去?肯定是1M的,所以首先要想方設(shè)法優(yōu)化包體大小

【優(yōu)化包體大小】的方法有哪些?

首先想下你的包體里面有啥?哪些東西占用的內(nèi)存最大,哪些東西壓縮的可能性最大?

項(xiàng)目路徑下有res、scenes、scripts,還有游戲引擎,等。

簡(jiǎn)言之,包體的組成分為:資源代碼

(1)資源:圖片、聲音、動(dòng)畫(huà)等。

避免大尺寸的圖片出現(xiàn):純色圖片或有規(guī)律的圖片用一像素的圖片表示,帶圓角的按鈕背景圖片用九宮格形式展示。

另外有一點(diǎn)也要格外注意,cocos creator所支持的最大圖片尺寸為2048*2048,超過(guò)這個(gè)尺寸的圖片在顯示時(shí)會(huì)有問(wèn)題,常見(jiàn)于一些Spine動(dòng)畫(huà)打包出來(lái)后沒(méi)注意資源圖片尺寸,導(dǎo)致動(dòng)畫(huà)顯示異常。

如果是地圖資源超過(guò)2048*2048,常見(jiàn)于一些mmo項(xiàng)目,這種情況下,需要對(duì)地圖資源進(jìn)行切分,切分成小于2048*2048的若干圖片,在游戲中再拼接在一起。

圖片壓縮

圖片的壓縮格式:背景,jpg體積要小于png,背景圖片jpg,很多圖片格式,導(dǎo)出美術(shù)圖后,這些圖,仍然可以壓縮。

百度搜索在線壓縮圖片,即可找到相應(yīng)網(wǎng)站直接操作。

圖片分辨率: 1920x1080 > 960x540,減少分辨率; -->降低了清晰度的;

盡可能的時(shí)候九宮格的圖片,來(lái)代替一張整圖按鈕200x100, 300x100; -->大大的降低的圖片的分斌率,這樣就可以節(jié)省資源;

類似這樣,將各個(gè)界面的美術(shù)資源、幀動(dòng)畫(huà)分類并且打包成圖集也是比較好的處理方法,將資源進(jìn)行模塊化。這樣在加載時(shí),以及游戲運(yùn)行時(shí),會(huì)有以下幾點(diǎn)好處:

1.提升加載速度

省去了多次打開(kāi)/關(guān)閉文件所帶來(lái)的時(shí)間損耗

2.減少文件的體積

多張圖片合并到一起,在包體上面會(huì)有一定的優(yōu)化

3.減少DrawCall

使用時(shí),由于這些美術(shù)資源都是一起配合使用的,因此放在一張圖集中,可以減少渲染的DrawCall數(shù)量,對(duì)渲染的性能也有優(yōu)化的作用。

同時(shí)在不需要使用這些資源時(shí),比如說(shuō)某個(gè)界面 不需要再顯示時(shí),可以將這個(gè)界面的資源統(tǒng)一釋放,避免占用內(nèi)存。

另外通用資源可以統(tǒng)一打包在一張圖集中,讓這些通用的常用資源常駐與內(nèi)存,方便使用。避免頻繁的重復(fù)釋放和加載。

同樣,聲音也可以采用相應(yīng)方法處理。

音樂(lè)音效資源(壓縮格式背景音樂(lè)的大小,音樂(lè)的數(shù)量,聲道,采樣率)。

如下是壓縮后的音樂(lè)文件和壓縮前的音樂(lè)文件大小對(duì)比,縮小為壓縮前的十分之一了。

字庫(kù)

盡可能的不要自己帶字庫(kù)。

(1)特效文字,盡量使用位圖字體,幾個(gè)字母+圖片,體積遠(yuǎn)遠(yuǎn)小于一個(gè)完整的字庫(kù),性能還要好,數(shù)字、界面的文字,例如我們的《極速賽車(chē)》中就是采用這種方案!

bmpfont -- .png + .fnt文件;

(2)盡可能的使用系統(tǒng)字庫(kù);

(3)字庫(kù)可以壓縮fontmin;特定的數(shù)量固定的文字;

(4)位圖字與矢量字,哪個(gè)性能更好? ? ?

位圖字:速度快,但是,內(nèi)存大;

矢量字:速度慢,但是內(nèi)存小;

【預(yù)制體】:

首先先說(shuō)一下prefab在使用時(shí)的步驟:從文件中讀取數(shù)據(jù) → 反序列化數(shù)據(jù) → 還原得到Prefab節(jié)點(diǎn)樹(shù) → 預(yù)處理 → 實(shí)例化

Prefab這塊的加載優(yōu)化主要集中在兩個(gè)地方:一個(gè)是load加載耗時(shí)優(yōu)化,另一個(gè)是實(shí)例化耗時(shí)優(yōu)化

①合理拆分Prefab

越大的prefab文件在加載過(guò)程中的耗時(shí)是越長(zhǎng)的,而且通常不是等比,而是以類似平方曲線這樣的去增加時(shí)長(zhǎng)的。

例如讀取一個(gè)100kb的文件,可能耗時(shí)也就10毫秒,但對(duì)于一個(gè)1M或者是2M的文件,我們?cè)诩虞d時(shí)就不是100毫秒,可能就是幾百毫秒。

類似這樣七八百kb的prefab文件,我們就要去思考一下,是不是里面的節(jié)點(diǎn)都必須做成一個(gè)prefab?

是否可以拆分成2個(gè)以上的prefab,通過(guò)拼接的方式組合?

一個(gè)prefab我們可以將它看作為一個(gè)功能模塊,而功能模塊并不是越大越好,而是功能職責(zé)越單一越好,遵循這個(gè)原則,我們可以對(duì)prefab做更好的拆分。

記住:職責(zé)單一原則,邏輯清晰,解耦,便于后期維護(hù)。加載快!!

②延遲加載資源

在場(chǎng)景處可以找到。

在Creator的資源管理器中點(diǎn)擊編輯好的prefab資源,在屬性檢查器中我們可以看到延遲加載資源的選項(xiàng)。勾選這個(gè)選項(xiàng)可以減少prefab的加載耗時(shí),但首次顯示的耗時(shí)會(huì)增加。

這是由于勾選后,Prefab所引用的資源,像圖片、音效這些,不會(huì)在load時(shí)加載,而是會(huì)在Prefab第一次顯示的時(shí)候再進(jìn)行資源的加載。因此需要根據(jù)具體的使用環(huán)境進(jìn)行選擇。

③選擇優(yōu)化策略

在prefab的屬性檢查器中,我們可以看到優(yōu)化策略這個(gè)選項(xiàng)。這個(gè)也需要我們根據(jù)實(shí)際的使用情況進(jìn)行選擇。

當(dāng)我們選擇“優(yōu)化多次創(chuàng)建性能”這個(gè)選項(xiàng)時(shí),Prefab加載后會(huì)進(jìn)行一個(gè)預(yù)處理的操作,這個(gè)預(yù)處理其實(shí)就是動(dòng)態(tài)生成一些prefab的實(shí)例化代碼,并把這些代碼交給jit去進(jìn)行優(yōu)化。

這樣在實(shí)例化時(shí)的耗時(shí)將會(huì)大大減少,相應(yīng)的,在load時(shí)的耗時(shí)會(huì)有所增加。

當(dāng)我們選擇“優(yōu)化單次創(chuàng)建性能”這個(gè)選項(xiàng)時(shí),prefab加載后會(huì)跳過(guò)預(yù)處理的步驟,這樣在加載時(shí)的耗時(shí)會(huì)減少很多,但實(shí)例化時(shí)的耗時(shí)會(huì)增加。例如一些固定UI界面,由于方便加載場(chǎng)景或者時(shí)進(jìn)行功能劃分,通常會(huì)做成prefab,這種prefab只會(huì)加載一次的,就可以選擇這個(gè)選項(xiàng),提升加載的性能。

需要注意的有一點(diǎn):由于微信小游戲平臺(tái)禁用了動(dòng)態(tài)加載代碼,類似eval這些不能使用,因此優(yōu)化策略這個(gè)選項(xiàng)在微信小游戲平臺(tái)是無(wú)效的。

(1)代碼:

代碼體積(引擎+業(yè)務(wù)邏輯代碼) -大頭在引擎。

解決方案:引擎:非常簡(jiǎn)單,你只要把不要的模塊去掉就可以了,你要知道哪些模塊是占體積多的,物理引擎,能不用的模塊,就不用。【項(xiàng)目設(shè)置】-【模塊設(shè)置】,只打包必要模塊即可。能不用tilemap就不用,因?yàn)镃ocos中有足夠優(yōu)秀的2D編輯器,可以替代tilemap,能用碰撞檢測(cè)引擎就不用物理引擎。可以通過(guò)項(xiàng)目設(shè)置,去掉游戲中沒(méi)有使用的功能模塊,減少包體大小。如下圖,將不需要的模塊去掉,再打包。

業(yè)務(wù)邏輯代碼一般我們也沒(méi)法修改,你的業(yè)務(wù)邏輯差不多,但是,要注意一個(gè)95%以上的同學(xué),都會(huì)忽略的一個(gè)事實(shí):src文件夾內(nèi)的settings文件。

其實(shí)settings文件大小是可以修改的。首先大家要搞明白它的大小是由誰(shuí)決定的? 如果你不搞清楚這個(gè)問(wèn)題,你就沒(méi)辦法優(yōu)化,即使別人告訴你這么做,你也會(huì)納悶。所有需要代碼加載的資源放到resources,否則堅(jiān)決不放到resources文件夾內(nèi)。因?yàn)槌绦虿恢滥男┵Y源需要加載,也不知道你什么時(shí)候加載,所以會(huì)一股腦在settings文件中建立資源的映射。如下圖所示,將資源放在res中和將資源放在resources文件夾下,settings文件的大小對(duì)比。

注意:需要清空build再打包。

2. 如何優(yōu)化渲染速度【渲染優(yōu)化】

渲染方面優(yōu)化主要集中在如何降低draw call上,draw call越多,渲染的壓力也就越大,對(duì)應(yīng)的幀率可能就會(huì)下降,正常情況下如果draw call超過(guò)100就有可能帶來(lái)卡頓,所以要注意這方面的優(yōu)化。

draw call:游戲場(chǎng)景里面物體,分幾次提交給顯卡繪制,這個(gè)次數(shù)就是等于drawall次數(shù)。

100個(gè)物體,100次提交給GPU,就是100個(gè)draw call。

draw call過(guò)高為什么會(huì)影響性能?

GPU:每次繪制我們的圖像---》一次能吞吐一定數(shù)目的三角形的,如果你的draw call過(guò)高,每次繪制的時(shí)候,GPU本來(lái)可以一次吃更多的三角形,但是你沒(méi)有讓我吃飽,GPU性能沒(méi)有發(fā)揮出來(lái)。

CPU:10個(gè)精靈,--》10張圖片;每次渲染管道里面再繪制的時(shí)候,只能帶一張紋理, 每個(gè)精靈的紋理對(duì)象,是不一樣的, 所以無(wú)法合批()

到底什么樣的能在一個(gè)draw call里面繪制呢?

mesh相同---紋理相同,shader要相同,參數(shù)要相同,draw call合批-- >繪制;

比如,10個(gè)物體:sprite1, sprite2, sprite3, label, 9宮格sprite, sprite;

推薦方法:

【1】合并渲染批次,降低 DrawCall,提升渲染性能

(1)使用自動(dòng)圖集或使用 TexturePacker 對(duì)碎圖進(jìn)行打包處理:只有圖集內(nèi)的精靈才有可能在一個(gè)draw call繪制→合批.這樣操作的話,可以讓多個(gè) Sprite 渲染的紋理都是同一張圖集圖片,合并這些 sprite 的渲染批次,就可以減少 DrawCall 以及 CPU 的運(yùn)算開(kāi)銷(xiāo)。

(2)合批的時(shí)候,盡可能的不要打亂了合批:例如上面label的出現(xiàn)打亂了sprite的結(jié)構(gòu),就不能合批。

(3)為什么label會(huì)單獨(dú)做一個(gè)draw call? 文字會(huì)繪制在紋理中。

(4)資源處理,減少 Mask 組件數(shù)量:由于 Mask 組件需要在 stencil 和 content 前后都添加修改 gl 狀態(tài)的 render command,因此使用 Mask 會(huì)打斷我們的 DrawCall 批處理。

對(duì)于一些特殊的顯示,例如圓角的 icon 等,如果條件允許,盡量不要使用 Mask 組件來(lái)進(jìn)行處理,而是通過(guò)對(duì)資源進(jìn)行處理達(dá)到同樣的效果。

目前 Mask 組件、Spine 組件、DragonBone 組件都會(huì)打斷批處理,在節(jié)點(diǎn)結(jié)構(gòu)上我們要避免被打斷的情況發(fā)生。

(5)復(fù)用節(jié)點(diǎn),減少節(jié)點(diǎn)數(shù):當(dāng)顯示或隱藏這個(gè)界面時(shí),大量的節(jié)點(diǎn)會(huì)帶來(lái)大量的 enable 和 disable 的開(kāi)銷(xiāo)。比如好友排行,假設(shè)有1000名好友,沒(méi)必要設(shè)置1000個(gè)節(jié)點(diǎn),設(shè)置一頁(yè)顯示的節(jié)點(diǎn)即可,之后更換這些節(jié)點(diǎn)的顯示內(nèi)容。

最快的辦法就是合并碎圖成圖集,然后同一圖集的按照順序擺放節(jié)點(diǎn),中間不能插入其他圖集的節(jié)點(diǎn)。

3. 內(nèi)存優(yōu)化

靜態(tài)資源的內(nèi)存管理:

靜態(tài)資源指的是場(chǎng)景中直接或間接引用到的所有資源(腳本動(dòng)態(tài)加載的資源不算在內(nèi))。

在場(chǎng)景資源的屬性編輯器中可以勾選“自動(dòng)釋放資源”選項(xiàng),從而在切換場(chǎng)景時(shí),會(huì)自動(dòng)將舊場(chǎng)景使用的靜態(tài)資源釋放掉,從而節(jié)省內(nèi)存的占用。

動(dòng)態(tài)資源的內(nèi)存管理:

動(dòng)態(tài)資源統(tǒng)一使用cc.loader進(jìn)行資源的加載以及管理。參考:動(dòng)態(tài)加載

要注意的一點(diǎn)是,CocosCreator中通過(guò)cc.loader去加載資源的所有方法,都是異步的。所以需要在回調(diào)中,確認(rèn)加載完成后才能使用資源。也可以通過(guò)cc.loader.getRes這個(gè)API去同步的獲取資源,但需要對(duì)get到的資源進(jìn)行檢查,如果沒(méi)有加載或者沒(méi)有加載完成,則需要等待或者通過(guò)cc.loader進(jìn)行加載。

這樣的話整個(gè)代碼會(huì)清晰一些,避免掉入JS的回調(diào)地獄中

例如:_loadRes = function(url, type, callback){

cc.loader.loadRes(url, type, function(){

if(!err){

callback(prefab);

}

});

}

Cc.loader.getRes

_createPrefab(url){

var prefab = cc.loader.getRes(url, cc.Prefab);

If(prefab !== null && typeof(prefab) !== "undefined"){

return cc.instantiate(prefab);

}

return null;

}

通過(guò)簡(jiǎn)單的封裝兩個(gè)方法,在使用時(shí)可以保持代碼的整潔易讀。

另外一點(diǎn)需要注意的是,當(dāng)批量進(jìn)行加載時(shí),cc.loader也提供了onProgress回調(diào),這個(gè)回調(diào)中的三個(gè)參數(shù)中。

totalCount并不是指的是加載的資源總個(gè)數(shù),而是加載這個(gè)資源所需要加載的依賴項(xiàng)個(gè)數(shù)。比如加載一個(gè)SpriteFrame,它的totalCount就是3,這3個(gè)item分別為:json,texture2D和SpriteFrame。

所以當(dāng)totalCount為0時(shí),并不是代表加載資源總個(gè)數(shù)為0,而是意味著這些資源已經(jīng)加載過(guò)在內(nèi)存中了,可以直接使用。

復(fù)用一切可復(fù)用的對(duì)象

最后是內(nèi)存使用的一個(gè)理念:復(fù)用一切可復(fù)用的對(duì)象。

復(fù)用,并不僅僅是為了節(jié)省對(duì)象在alloc造成的開(kāi)銷(xiāo),更重要的是避免GC時(shí)帶來(lái)的額外開(kāi)銷(xiāo)。

像一些戰(zhàn)斗中的掉血數(shù)字,敵人的血槽,怪物,子彈,英雄頭像等等,都是我們常常回去做復(fù)用的地方。

對(duì)于常見(jiàn)一些復(fù)雜對(duì)象,我們可以使用對(duì)象池NodePool進(jìn)行復(fù)用

對(duì)于基礎(chǔ)的對(duì)象我們可以直接進(jìn)行賦值從而達(dá)到復(fù)用的目的。

1. CPU及性能優(yōu)化

1、絕對(duì)避免游戲中出現(xiàn)死循環(huán)。

2、控制游戲幀率。

3、H5游戲,JS代碼級(jí)別優(yōu)化

for(var i=0,len=arr.length; i<len; i++){

}

4.JS異常捕獲

Try_catch

一單拋出異常,效率就會(huì)直線下降。盡量避免在for循環(huán)中try。。

5.全局變量的使用要慎重!!

6、優(yōu)化節(jié)點(diǎn)樹(shù),減少節(jié)點(diǎn)數(shù)量。

7、場(chǎng)景中不要掛載過(guò)多的Prefab,可適當(dāng)將一些Prefab變成動(dòng)態(tài)加載的。

四、 性能優(yōu)化應(yīng)注意什么?

效率、成本。不要花百分之九十的時(shí)間、成本去嘗試獲取百分之一的性能提升。

很多時(shí)候,需要兩害相權(quán)取其輕。點(diǎn)擊鏈接加入群聊【Unity/Cocos交流群】

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容