如何將HTML5性能發(fā)揮到極致
HTML5作為新興領(lǐng)域越來(lái)越熱。然而在移動(dòng)設(shè)備硬件性能弱于PC的背景下,對(duì)性能的需求顯得更為重要,而HTML5性能優(yōu)化前與優(yōu)化后有著極大的差別,如何優(yōu)化才能提高性能,對(duì)此熟知的人很少。本文以LayaAir引擎為例,通過(guò)代碼示例詳細(xì)闡述如何利用引擎對(duì)HTML5作出性能的極致優(yōu)化。
主題包括:
- 代碼執(zhí)行基本原理
- 基準(zhǔn)測(cè)試
- 內(nèi)存優(yōu)化
- 圖形渲染性能
- 減少CPU使用量
- 其他優(yōu)化策略
第1節(jié):代碼執(zhí)行基本原理
LayaAir引擎支持AS3、TypeScript、JavaScript三種語(yǔ)言開(kāi)發(fā),然而無(wú)論是采用哪種開(kāi)發(fā)語(yǔ)言,最終執(zhí)行的都是JavaScript代碼。所有看到的畫(huà)面都是通過(guò)引擎繪制出來(lái)的,更新頻率取決于開(kāi)發(fā)者指定的FPS,例如指定幀頻率為60FPS,則運(yùn)行時(shí)每個(gè)幀的執(zhí)行時(shí)間為六十分之一秒,所以幀速越高,視覺(jué)上感覺(jué)越流暢,60幀是滿幀。
由于實(shí)際運(yùn)行環(huán)境是在瀏覽器中,因此性能還取決于JavaScript解釋器的效率,指定的FPS幀速在低性能解釋器中可能不會(huì)達(dá)到,所以這部分不是開(kāi)發(fā)者能夠決定的,開(kāi)發(fā)者能作的是盡可能通過(guò)優(yōu)化,在低端設(shè)備或低性能瀏覽器中,提升FPS幀速。
LayaAir引擎在每幀都會(huì)重繪,在性能優(yōu)化時(shí),除了關(guān)注每幀執(zhí)行邏輯代碼帶來(lái)的CPU消耗,還需要注意每幀調(diào)用繪圖指令的數(shù)量以及GPU的紋理提交次數(shù)。
第2節(jié):基準(zhǔn)測(cè)試
LayaAir引擎內(nèi)置的性能統(tǒng)計(jì)工具可用于基準(zhǔn)測(cè)試,實(shí)時(shí)檢測(cè)當(dāng)前性能。開(kāi)發(fā)者可以使用laya.utils.Stat類,通過(guò)Stat.show() 顯示統(tǒng)計(jì)面板。具體編寫(xiě)代碼如下例所示:
- Stat.show(0,0); //AS3的面板調(diào)用寫(xiě)法
- Laya.Stat.show(0,0); //TS與JS的面板調(diào)用寫(xiě)法
Canvas渲染的統(tǒng)計(jì)信息:
WebGL渲染的統(tǒng)計(jì)信息:
統(tǒng)計(jì)參數(shù)的意義:
FPS:
- 每秒呈現(xiàn)的幀數(shù)(數(shù)字越高越好)。
- 使用canvas渲染時(shí),描述字段顯示為FPS(Canvas),使用WebGL渲染時(shí),描述字段顯示為FPS(WebGL)。
Sprite:
- 渲染節(jié)點(diǎn)數(shù)量(數(shù)字越低越好)。
- Sprite統(tǒng)計(jì)所有渲染節(jié)點(diǎn)(包括容器),這個(gè)數(shù)字的大小會(huì)影響引擎節(jié)點(diǎn)遍歷,數(shù)據(jù)組織和渲染的次數(shù)。
DrawCall:
- DrawCall在canvas和WebGL渲染下代表不同的意義(越少越好)。
- Canvas下表示每幀的繪制次數(shù),包括圖片、文字、矢量圖。盡量限制在100之下。
- WebGL下表示渲染提交批次,每次準(zhǔn)備數(shù)據(jù)并通知GPU渲染繪制的過(guò)程稱為1次DrawCall,在每1次DrawCall中除了在通知GPU的渲染上比較耗時(shí)之外,切換材質(zhì)與shader也是非常耗時(shí)的操作。 DrawCall的次數(shù)是決定性能的重要指標(biāo),盡量限制在100之下。
Canvas:
三個(gè)數(shù)值 —— 每幀重繪的畫(huà)布數(shù)量 / 緩存類型為“normal”類型的畫(huà)布數(shù)量 / 緩存類型為“bitmap”類型的畫(huà)布數(shù)量”。
CurMem:僅限WebGL渲染,表示內(nèi)存與顯存占用(越低越好)。
Shader:僅限WebGL渲染,表示每幀Shader提交次數(shù)。
無(wú)論是Canvas模式還是WebGL模式,我們都需要重點(diǎn)關(guān)注DrawCall,Sprite,Canvas這三個(gè)參數(shù),然后針對(duì)性地進(jìn)行優(yōu)化。(參見(jiàn)“圖形渲染性能”)
第3節(jié):內(nèi)存優(yōu)化
對(duì)象池
對(duì)象池,涉及到不斷重復(fù)使用對(duì)象。在初始化應(yīng)用程序期間創(chuàng)建一定數(shù)量的對(duì)象并將其存儲(chǔ)在一個(gè)池中。對(duì)一個(gè)對(duì)象完成操作后,將該對(duì)象放回到池中,在需要新對(duì)象時(shí)可以對(duì)其進(jìn)行檢索。
由于實(shí)例化對(duì)象成本很高,使用對(duì)象池重用對(duì)象可減少實(shí)例化對(duì)象的需求。還可以減少垃圾回收器運(yùn)行的機(jī)會(huì),從而提高程序的運(yùn)行速度。
以下代碼演示使用
Laya.utils.Pool:
- ar SPRITE_SIGN = 'spriteSign';
- var sprites = [];
- function initialize()
- {
- for (var i = 0; i < 1000; i++)
- {
- var sp = Pool.getItemByClass(SPRITE_SIGN, Sprite)
- sprites.push(sp);
- Laya.stage.addChild(sp);
- }
- }
- initialize();
在initialize中創(chuàng)建大小為1000的對(duì)象池。
以下代碼在當(dāng)單擊鼠標(biāo)時(shí),將刪除顯示列表中的所有顯示對(duì)象,并在以后的其他任務(wù)中重復(fù)使用這些對(duì)象:
- Laya.stage.on("click", this, function()
- {
- var sp;
- for(var i = 0, len = sprites.length; i < len; i++)
- {
- sp = sprites.pop();
- Pool.recover(SPRITE_SIGN, sp);
- Laya.stage.removeChild(sp);
- }
- });
調(diào)用Pool.recover后,指定的對(duì)象會(huì)被回收至池內(nèi)。
使用Handler.create
在開(kāi)發(fā)過(guò)程中,會(huì)經(jīng)常使用Handler來(lái)完成異步回調(diào)。Handler.create使用了內(nèi)置對(duì)象池管理,因此在使用Handler對(duì)象時(shí)應(yīng)使用Handler.create來(lái)創(chuàng)建回調(diào)處理器。以下代碼使用Handler.create創(chuàng)建加載的回調(diào)處理器:
- Laya.loader.load(urls, Handler.create(this, onAssetLoaded));
在上面的代碼中,回調(diào)被執(zhí)行后Handler將會(huì)被對(duì)象池收回。此時(shí),考慮如下代碼會(huì)發(fā)生什么事:
- Laya.loader.load(urls, Handler.create(this, onAssetLoaded), Handler.create(this, onLoading));
在上面的代碼中,使用Handler.create返回的處理器處理progress事件。此時(shí)的回調(diào)執(zhí)行一次之后就被對(duì)象池回收,于是progress事件只觸發(fā)了一次,此時(shí)需要將四個(gè)名為once的參數(shù)設(shè)置為false:
- Laya.loader.load(urls, Handler.create(this, onAssetLoaded), Handler.create(this, onLoading, null, false));
釋放內(nèi)存
JavaScript運(yùn)行時(shí)無(wú)法啟動(dòng)垃圾回收器。要確保一個(gè)對(duì)象能夠被回收,請(qǐng)刪除對(duì)該對(duì)象的所有引用。Sprite提供的destory會(huì)幫助設(shè)置內(nèi)部引用為null。
例如,以下代碼確保對(duì)象能夠被作為垃圾回收:
- var sp = new Sprite();
- sp.destroy();
當(dāng)對(duì)象設(shè)置為null,不會(huì)立即將其從內(nèi)存中刪除。只有系統(tǒng)認(rèn)為內(nèi)存足夠低時(shí),垃圾回收器才會(huì)運(yùn)行。內(nèi)存分配(而不是對(duì)象刪除)會(huì)觸發(fā)垃圾回收。
垃圾回收期間可能占用大量CPU并影響性能。通過(guò)重用對(duì)象,嘗試限制使用垃圾回收。此外,盡可能將引用設(shè)置為null,以便垃圾回收器用較少時(shí)間來(lái)查找對(duì)象。有時(shí)(比如兩個(gè)對(duì)象相互引用),無(wú)法同時(shí)設(shè)置兩個(gè)引用為null,垃圾回收器將掃描無(wú)法被訪問(wèn)到的對(duì)象,并將其清除,這會(huì)比引用計(jì)數(shù)更消耗性能。
資源卸載
游戲運(yùn)行時(shí)總會(huì)加載許多資源,這些資源在使用完成后應(yīng)及時(shí)卸載,否則一直殘留在內(nèi)存中。
下例演示加載資源后對(duì)比資源卸載前和卸載后的資源狀態(tài):
- var assets = [];
- assets.push("res/apes/monkey0.png");
- assets.push("res/apes/monkey1.png");
- assets.push("res/apes/monkey2.png");
- assets.push("res/apes/monkey3.png");
- Laya.loader.load(assets, Handler.create(this, onAssetsLoaded));
- function onAssetsLoaded()
- {
- for(var i = 0, len = assets.length; i < len; ++i)
- {
- var asset = assets[i];
- console.log(Laya.loader.getRes(asset));
- Laya.loader.clearRes(asset);
- console.log(Laya.loader.getRes(asset));
- }
- }
關(guān)于濾鏡、遮罩
嘗試盡量減少使用濾鏡效果。將濾鏡(BlurFilter和GlowFilter)應(yīng)用于顯示對(duì)象時(shí),運(yùn)行時(shí)將在內(nèi)存中創(chuàng)建兩張位圖。其中每個(gè)位圖的大小與顯示對(duì)象相同。將第一個(gè)位圖創(chuàng)建為顯示對(duì)象的柵格化版本,然后用于生成應(yīng)用濾鏡的另一個(gè)位圖:
應(yīng)用濾鏡時(shí)內(nèi)存中的兩個(gè)位圖
當(dāng)修改濾鏡的某個(gè)屬性或者顯示對(duì)象時(shí),內(nèi)存中的兩個(gè)位圖都將更新以創(chuàng)建生成的位圖,這兩個(gè)位圖可能會(huì)占用大量?jī)?nèi)存。此外,此過(guò)程涉及CPU計(jì)算,動(dòng)態(tài)更新時(shí)將會(huì)降低性能(參見(jiàn)“圖形渲染性能 – 關(guān)于cacheAs)。
ColorFiter在Canvas渲染下需要計(jì)算每個(gè)像素點(diǎn),而在WebGL下的GPU消耗可以忽略不計(jì)。
最佳的做法是,盡可能使用圖像創(chuàng)作工具創(chuàng)建的位圖來(lái)模擬濾鏡。避免在運(yùn)行時(shí)中創(chuàng)建動(dòng)態(tài)位圖,可以幫助減少CPU或GPU負(fù)載。特別是一張應(yīng)用了濾鏡并且不會(huì)在修改的圖像。
第4節(jié):圖形渲染性能
優(yōu)化Sprite
- 盡量減少不必要的層次嵌套,減少Sprite數(shù)量。
- 非可見(jiàn)區(qū)域的對(duì)象盡量從顯示列表移除或者設(shè)置visible=false。
- 對(duì)于容器內(nèi)有大量靜態(tài)內(nèi)容或者不經(jīng)常變化的內(nèi)容(比如按鈕),可以對(duì)整個(gè)容器設(shè)置cacheAs屬性,能大量減少Sprite的數(shù)量,顯著提高性能。如果有動(dòng)態(tài)內(nèi)容,最好和靜態(tài)內(nèi)容分開(kāi),以便只緩存靜態(tài)內(nèi)容。
- Panel內(nèi),會(huì)針對(duì)panel區(qū)域外的直接子對(duì)象(子對(duì)象的子對(duì)象判斷不了)進(jìn)行不渲染處理,超出panel區(qū)域的子對(duì)象是不產(chǎn)生消耗的。
優(yōu)化DrawCall
- 對(duì)復(fù)雜靜態(tài)內(nèi)容設(shè)置cacheAs,能大量減少DrawCall,使用好cacheAs是游戲優(yōu)化的關(guān)鍵。
- 盡量保證同圖集的圖片渲染順序是挨著的,如果不同圖集交叉渲染,會(huì)增加DrawCall數(shù)量。
- 盡量保證同一個(gè)面板中的所有資源用一個(gè)圖集,這樣能減少提交批次。
優(yōu)化Canvas
在對(duì)Canvas優(yōu)化時(shí),我們需要注意,在以下場(chǎng)合不要使用cacheAs:
- 對(duì)象非常簡(jiǎn)單,比如一個(gè)字或者一個(gè)圖片,設(shè)置cacheAs=bitmap不但不提高性能,反而會(huì)損失性能。
- 容器內(nèi)有經(jīng)常變化的內(nèi)容,比如容器內(nèi)有一個(gè)動(dòng)畫(huà)或者倒計(jì)時(shí),如果再對(duì)這個(gè)容器設(shè)置cacheAs=bitmap,會(huì)損失性能。
可以通過(guò)查看Canvas統(tǒng)計(jì)信息的第一個(gè)值,判斷是否一直在刷新Canvas緩存。
關(guān)于cacheAs
設(shè)置cacheAs可將顯示對(duì)象緩存為靜態(tài)圖像,當(dāng)cacheAs時(shí),子對(duì)象發(fā)生變化,會(huì)自動(dòng)重新緩存,同時(shí)也可以手動(dòng)調(diào)用reCache方法更新緩存。 建議把不經(jīng)常變化的復(fù)雜內(nèi)容,緩存為靜態(tài)圖像,能極大提高渲染性能,cacheAs有”none”,”normal”和”bitmap”三個(gè)值可選。
- 默認(rèn)為”none”,不做任何緩存。
- 當(dāng)值為”normal”時(shí),canvas下進(jìn)行畫(huà)布緩存,webgl模式下進(jìn)行命令緩存。
- 當(dāng)值為”bitmap”時(shí),canvas下進(jìn)行依然是畫(huà)布緩存,webGL模式下使用renderTarget緩存。這里需要注意的是,webGL下renderTarget緩存模式有2048大小限制,超出2048會(huì)額外增加內(nèi)存開(kāi)銷。另外,不斷重繪時(shí)開(kāi)銷也比較大,但是會(huì)減少drawcall,渲染性能最高。 webGL下命令緩存模式只會(huì)減少節(jié)點(diǎn)遍歷及命令組織,不會(huì)減少drawcall,性能中等。
設(shè)置cacheAs后,還可以設(shè)置staticCache=true以阻止自動(dòng)更新緩存,同時(shí)可以手動(dòng)調(diào)用reCache方法更新緩存。
cacheAs主要通過(guò)兩方面提升性能。一是減少節(jié)點(diǎn)遍歷和頂點(diǎn)計(jì)算;二是減少drawCall。善用cacheAs將是引擎優(yōu)化性能的利器。
下例繪制10000個(gè)文本:
- Laya.init(550, 400, Laya.WebGL);
- Laya.Stat.show();
- var textBox = new Laya.Sprite();
- var text;
- for (var i = 0; i < 10000; i++)
- {
- text = new Laya.Text();
- text.text = (Math.random() * 100).toFixed(0);
- text.color = "#CCCCCC";
- text.x = Math.random() * 550;
- text.y = Math.random() * 400;
- textBox.addChild(text);
- }
- Laya.stage.addChild(textBox);
下面是筆者電腦上的運(yùn)行時(shí)截圖,F(xiàn)PS穩(wěn)定于52上下。
當(dāng)我們對(duì)文字所在的容器設(shè)置為cacheAs之后,如下面的例子所示,性能獲得較大的提升,F(xiàn)PS達(dá)到到了60幀。
- // …省略其他代碼… var textBox = new Laya.Sprite();
- textBox.cacheAs = "bitmap"; // …省略其他代碼…
文字描邊
在運(yùn)行時(shí),設(shè)置了描邊的文本比沒(méi)有描邊的文本多調(diào)用一次繪圖指令。此時(shí),文本對(duì)CPU的使用量和文本的數(shù)量成正比。因此,盡量使用替代方案來(lái)完成同樣的需求。
對(duì)于幾乎不變動(dòng)的文本內(nèi)容,可以使用cacheAs降低性能消耗,參見(jiàn)“圖形渲染性能 – 關(guān)于cacheAs”。
對(duì)于內(nèi)容經(jīng)常變動(dòng),但是使用的字符數(shù)量較少的文本域,可以選擇使用位圖字體。
跳過(guò)文本排版,直接渲染
大多數(shù)情況下,很多文本都不需要復(fù)雜的排版,僅僅簡(jiǎn)單地顯示一行字。為了迎合這一需求,Text提供的名為changeText的方法可以直接跳過(guò)排版。
- var text = new Text();
- text.text = "text";
- Laya.stage.addChild(text);
- //后面只是更新文字內(nèi)容,使用changeText能提高性能
- text.changeText("text changed.");
Text.changeText會(huì)直接修改繪圖指令中該文本繪制的最后一條指令,這種前面的繪圖指令依舊存在的行為會(huì)導(dǎo)致changeText只使用于以下情況:
- 文本始終只有一行。
- 文本的樣式始終不變(顏色、粗細(xì)、斜體、對(duì)齊等等)。
即使如此,實(shí)際編程中依舊會(huì)經(jīng)常使用到這樣的需要。
第5節(jié):減少CPU使用量
減少動(dòng)態(tài)屬性查找
JavaScript中任何對(duì)象都是動(dòng)態(tài)的,你可以任意地添加屬性。然而,在大量的屬性里查找某屬性可能很耗時(shí)。如果需要頻繁使用某個(gè)屬性值,可以使用局部變量來(lái)保存它:
- function foo()
- {
- var prop = target.prop;
- // 使用prop
- process1(prop);
- process2(prop);
- process3(prop);
- }
計(jì)時(shí)器
LayaAir提供兩種計(jì)時(shí)器循環(huán)來(lái)執(zhí)行代碼塊。
- Laya.timer.frameLoop執(zhí)行頻率依賴于幀頻率,可通過(guò)Stat.FPS查看當(dāng)前幀頻。
- Laya.timer.loop執(zhí)行頻率依賴于參數(shù)指定時(shí)間。
當(dāng)一個(gè)對(duì)象的生命周期結(jié)束時(shí),記得清除其內(nèi)部的Timer:
- Laya.timer.frameLoop(1, this, animateFrameRateBased);
- Laya.stage.on("click", this, dispose);
- function dispose()
- {
- Laya.timer.clear(this, animateFrameRateBased);
- }
獲取顯示對(duì)象邊界的做法
在相對(duì)布局中,很經(jīng)常需要正確地獲取顯示對(duì)象的邊界。獲取顯示對(duì)象的邊界也有多種做法,而其間差異很有必要知道。
1.使用getBounds/ getGraphicBounds。、
- var sp = new Sprite();
- sp.graphics.drawRect(0, 0, 100, 100, "#FF0000");
- var bounds = sp.getGraphicBounds();
- Laya.stage.addChild(sp);
getBounds可以滿足多數(shù)多數(shù)需求,但由于其需要計(jì)算邊界,不適合頻繁調(diào)用。
2.設(shè)置容器的autoSize為true。
- var sp = new Sprite();
- sp.autoSize = true;
- sp.graphics.drawRect(0, 0, 100, 100, "#FF0000");
- Laya.stage.addChild(sp);
上述代碼可以在運(yùn)行時(shí)正確獲取寬高。autoSize在獲取寬高并且顯示列表的狀態(tài)發(fā)生改變時(shí)會(huì)重新計(jì)算(autoSize通過(guò)getBoudns計(jì)算寬高)。所以對(duì)擁有大量子對(duì)象的容器應(yīng)用autoSize是不可取的。如果設(shè)置了size,autoSize將不起效。
使用loadImage后獲取寬高:
- var sp = new Sprite();
- sp.loadImage("res/apes/monkey2.png", 0, 0, 0, 0, Handler.create(this, function()
- {
- console.log(sp.width, sp.height);
- }));
- Laya.stage.addChild(sp);
loadImage在加載完成的回調(diào)函數(shù)觸發(fā)之后才可以正確獲取寬高。
3.直接調(diào)用size設(shè)置:
- Laya.loader.load("res/apes/monkey2.png", Handler.create(this, function()
- {
- var texture = Laya.loader.getRes("res/apes/monkey2.png");
- var sp = new Sprite();
- sp.graphics.drawTexture(texture, 0, 0);
- sp.size(texture.width, texture.height);
- Laya.stage.addChild(sp);
- }));
使用Graphics.drawTexture并不會(huì)自動(dòng)設(shè)置容器的寬高,但是可以使用Texture的寬高賦予容器。毋庸置疑,這是最高效的方式。
注:getGraphicsBounds用于獲取矢量繪圖寬高。
根據(jù)活動(dòng)狀態(tài)改變幀頻
幀頻有三種模式,Stage.FRAME_SLOW維持FPS在30;Stage.FRAME_FAST維持FPS在60;Stage.FRAME_MOUSE則選擇性維持FPS在30或60幀。
有時(shí)并不需要讓游戲以60FPS的速率執(zhí)行,因?yàn)?0FPS已經(jīng)能夠滿足多數(shù)情況下人類視覺(jué)的響應(yīng),但是鼠標(biāo)交互時(shí),30FPS可能會(huì)造成畫(huà)面的不連貫,于是Stage.FRAME_MOUSE應(yīng)運(yùn)而生。
下例展示以Stage.FRAME_SLOW的幀率,在畫(huà)布上移動(dòng)鼠標(biāo),使圓球跟隨鼠標(biāo)移動(dòng):
- Laya.init(Browser.width, Browser.height);
- Stat.show();
- Laya.stage.frameRate = Stage.FRAME_SLOW;
- var sp = new Sprite();
- sp.graphics.drawCircle(0, 0, 20, "#990000");
- Laya.stage.addChild(sp);
- Laya.stage.on(Event.MOUSE_MOVE, this, function()
- {
- sp.pos(Laya.stage.mouseX, Laya.stage.mouseY);
- });
此時(shí)FPS顯示30,并且在鼠標(biāo)移動(dòng)時(shí),可以感覺(jué)到圓球位置的更新不連貫。設(shè)置Stage.frameRate為Stage.FRAME_MOUSE:
- Laya.stage.frameRate = Stage.FRAME_MOUSE;
此時(shí)在鼠標(biāo)移動(dòng)后FPS會(huì)顯示60,并且畫(huà)面流暢度提升。在鼠標(biāo)靜止2秒不動(dòng)后,F(xiàn)PS又會(huì)恢復(fù)到30幀。
使用callLater
callLater使代碼塊延遲至本幀渲染前執(zhí)行。如果當(dāng)前的操作頻繁改變某對(duì)象的狀態(tài),此時(shí)可以考慮使用callLater,以減少重復(fù)計(jì)算。
考慮一個(gè)圖形,對(duì)它設(shè)置任何改變外觀的屬性都將導(dǎo)致圖形重繪:
- var rotation = 0,
- scale = 1,
- position = 0;
- function setRotation(value)
- {
- this.rotation = value;
- update();
- }
- function setScale(value)
- {
- this.scale = value;
- update();
- }
- function setPosition(value)
- {
- this.position = value;
- update();
- }
- function update()
- {
- console.log('rotation: ' + this.rotation + '\tscale: ' + this.scale + '\tposition: ' + position);
- }
調(diào)用以下代碼更改狀態(tài):
- setRotation(90); setScale(2); setPosition(30);
控制臺(tái)的打印結(jié)果是
- rotation: 90 scale: 1 position: 0
- rotation: 90 scale: 2 position: 0
- rotation: 90 scale: 2 position: 30
update被調(diào)用了三次,并且最后的結(jié)果是正確的,但是前面兩次調(diào)用都是不需要的。
嘗試將三處update改為:
- Laya.timer.callLater(this, update);
此時(shí),update只會(huì)調(diào)用一次,并且是我們想要的結(jié)果。
圖片/圖集加載
在完成圖片/圖集的加載之后,引擎就會(huì)開(kāi)始處理圖片資源。如果加載的是一張圖集,會(huì)處理每張子圖片。如果一次性處理大量的圖片,這個(gè)過(guò)程可能會(huì)造成長(zhǎng)時(shí)間的卡頓。
在游戲的資源加載中,可以將資源按照關(guān)卡、場(chǎng)景等分類加載。在同一時(shí)間處理的圖片越少,當(dāng)時(shí)的游戲響應(yīng)速度也會(huì)更快。在資源使用完成后,也可以予以卸載,釋放內(nèi)存。
第6節(jié):其他優(yōu)化策略
- 減少粒子使用數(shù)量,在移動(dòng)平臺(tái)Canvas模式下,盡量不用粒子;
- 在Canvas模式下,盡量減少旋轉(zhuǎn),縮放,alpha等屬性的使用,這些屬性會(huì)對(duì)性能產(chǎn)生消耗。(在WebGL模式可以使用);
- 不要在timeloop里面創(chuàng)建對(duì)象及復(fù)雜計(jì)算;
- 盡量減少對(duì)容器的autoSize的使用,減少getBounds()的使用,因?yàn)檫@些調(diào)用會(huì)產(chǎn)生較多計(jì)算;
- 盡量少用try catch的使用,被try catch的函數(shù)執(zhí)行會(huì)變得非常慢;