LayaAir 物件池 laya.utils.Pool
目錄
物件池優化記憶體
1、物件池優化是遊戲開發中非常重要的優化方式,也是影響遊戲效能的重要因素之一。
2、遊戲中有許多物件會不停的建立與移除,比如角色攻擊子彈、特效的建立與移除,NPC(非玩家角色)的被消滅與重新整理等,在建立過程中非常消耗效能,特別是數量多的情況下。
3、物件池技術能很好解決以上問題,在物件移除消失的時候回收到物件池,需要新物件的時候直接從物件池中取出使用。
4、物件池的優點是減少了例項化物件時的開銷,且能讓物件反覆使用,減少了新記憶體分配與垃圾回收器執行的機會。
5、注意:物件移除時並不是立即從記憶體中抹去,只有認為記憶體不足時,才會使用垃圾回收機制清空,清空時很耗記憶體,很可能就會造成卡頓現象。用了物件池後將減少程式的垃圾物件,有效的提高程式的執行速度和穩定性。
物件池 Pool
Package | laya.utils |
類 | public class Pool |
Inheritance | Pool Object |
1、Pool 是物件池類,用於物件的存貯、重複使用。合理使用物件池,可以有效減少物件建立的開銷,避免頻繁的垃圾回收,從而優化遊戲流暢度。
Method(方法) | |
---|---|
clearBySign(sign:String):void ,[static] 清除物件池的物件。 | Pool |
getItem(sign:String):* ,[static] 根據傳入的物件型別標識字元,獲取物件池中已儲存的此型別的一個物件,如果物件池中無此型別的物件,則返回 null 。 |
Pool |
getItemByClass(sign:String, cls:Class):* [static] 根據傳入的物件型別標識字元,獲取物件池中此型別標識的一個物件例項。 當物件池中無此型別標識的物件時,則根據傳入的型別,建立一個新的物件返回。 |
Pool |
[static] 根據傳入的物件型別標識字元,獲取物件池中此型別標識的一個物件例項。 當物件池中無此型別標識的物件時,則使用傳入的建立此型別物件的函式,新建一個物件返回。 |
Pool |
getPoolBySign(sign:String):Array ,[static] 根據物件型別標識字元,獲取物件池。 |
Pool |
recover(sign:String, item:Object):void ,[static] 將物件放到對應型別標識的物件池中。 |
Pool |
官網 API:https://layaair.ldc.layabox.com/api/?category=Core&class=laya.utils.Pool
2、其中較常用是 getItemByClass() 與 recover() 方法。
/**
* <p>根據傳入的物件型別標識字元,獲取物件池中此型別標識的一個物件例項。</p>
* <p>當物件池中無此型別標識的物件時,則根據傳入的型別,建立一個新的物件返回。</p>
* @param sign 物件型別標識字元。
* @param cls 用於建立該型別物件的類。
* @return 此型別標識的一個物件。
*/
static getItemByClass(sign: string, cls: any): any;
/**
* 將物件放到對應型別標識的物件池中。
* @param sign 物件型別標識字元。
* @param item 物件。
*/
static recover(sign: string, item: any): void;
編碼示例
如上所示演示每隔 100 幀使用物件池方法建立 100 個雪花,當雪花移動超出邊界或縮放小於 0 時進行了移除舞臺,並呼叫Pool.recover() 方法,使指定的物件回收至物件池內。
Laya.init(1136, 640, Laya.WebGL);//初始化引擎,不支援 WebGL自動切換為Canvas
Laya.Stat.show(0, 0);/**顯示效能面板 */
Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;//按照最小比率縮放
Laya.stage.bgColor = "#232628";//背景顏色
Laya.timer.frameLoop(1, this, onFrame);//幀迴圈,每隔1幀呼叫一次 onFrame函式
var createTime = 0;
/**幀動畫回撥 */
function onFrame() {
//如果建立物件時間為100幀間隔後,即間隔100幀(約1.6秒)生成100個雪花從天而降
if (createTime >= 100) {
for (var i = 0; i < 100; i++) {//每100幀間隔建立100個雪花
/**
* 不使用物件池寫法:var img = new Image();
*/
//通過物件池建立圖片,如物件池中無相應的物件,則根據Image型別執行new Image()建立
/**
* getItemByClass(sign: string, cls: any) 根據傳入的物件型別標識字元,獲取物件池中此型別標識的一個物件例項.
* 當物件池中無此型別標識的物件時,則根據傳入的型別,建立一個新的物件返回.
* sign 物件型別標識字元.cls 用於建立該型別物件的類[email protected] 此型別標識的一個物件
*/
var img = Laya.Pool.getItemByClass("snowflake", Laya.Image);
img.anchorX = img.anchorY = 0.5;//通過錨點設定軸心點,值為0-1
img.skin = "res/snow0.png"//設定圖片資源(面板),圖片尺寸 100 * 100
//在舞臺上方隨機位置建立
img.x = Math.random() * Laya.stage.width;
img.y = Math.random() * -150;
/**
* 因為雪花在下落過程中會逐漸減小 scaleX、scaleY,從而讓雪花看起來越來越小
* 當超出邊界後會將雪花(圖片)物件回收到物件池,所裡從物件池中的取出的圖片是被縮放了的,這裡需重置其縮放屬性
* 同理如果物件中還有其他屬性被改變了,下落之前也應該進行重置
*/
img.scaleX = img.scaleY = 1;
Laya.stage.addChild(img);//載入到舞臺顯示
createTime = 0;//100幀後建立完物件後時間將時間歸0
}
} else {
createTime++;//更新建立時間
}
animation();
}
/**重新整理整個舞臺中的所有雪花的位置以及狀態資訊 */
function animation() {
/**
* readonly numChildren: number 子物件數量,這是超類 laya.display.Node 中的屬性
* getChildAt(index: number): Node 根據子節點的索引位置,獲取子節點物件。繼承自超類 laya.display.Node
*/
for (var j = 0; j < Laya.stage.numChildren; j++) {
var img = Laya.stage.getChildAt(j);
img.y++;//位置更新,垂直降落
img.scaleX -= 0.001;//對雪花大小進行縮放
img.scaleY -= 0.001;//對雪花大小進行縮放
img.rotation++;//對雪花(圖片)進行旋轉
//超出邊界或縮放小於0時,將物件進行回收並從舞臺中清除
if (img.y > Laya.stage.height || img.scaleX <= 0) {
/**removeChild(node: Node): Node 刪除子節點
* 從舞臺中移除雪花(圖片),繼承自超類 laya.display.Node */
Laya.stage.removeChild(img);
/**recover(sign: string, item: any) 將物件放到對應型別標識的物件池中。
* sign 物件型別標識字元。item 物件。
*/
Laya.Pool.recover("snowflake", img);
// img.destroy(); //不使用物件池的編寫方式時,直接用destroy清空
}
}
}
示例使用的圖片資源: