1. 程式人生 > >LayaAir 物件池 laya.utils.Pool

LayaAir 物件池 laya.utils.Pool

目錄

物件池優化記憶體

物件池 Pool

編碼示例


物件池優化記憶體

1、物件池優化是遊戲開發中非常重要的優化方式,也是影響遊戲效能的重要因素之一。

2、遊戲中有許多物件會不停的建立與移除,比如角色攻擊子彈、特效的建立與移除,NPC(非玩家角色)的被消滅與重新整理等,在建立過程中非常消耗效能,特別是數量多的情況下。

3、物件池技術能很好解決以上問題,在物件移除消失的時候回收到物件池,需要新物件的時候直接從物件池中取出使用。

4、物件池的優點是減少了例項化物件時的開銷,且能讓物件反覆使用,減少了新記憶體分配與垃圾回收器執行的機會。

5、注意:物件移除時並不是立即從記憶體中抹去,只有認為記憶體不足時,才會使用垃圾回收機制清空,清空時很耗記憶體,很可能就會造成卡頓現象。用了物件池後將減少程式的垃圾物件,有效的提高程式的執行速度和穩定性。

物件池 Pool

Package laya.utils
public class Pool
Inheritance Pool Inheritance Object

1、Pool 是物件池類,用於物件的存貯、重複使用。合理使用物件池,可以有效減少物件建立的開銷,避免頻繁的垃圾回收,從而優化遊戲流暢度。

Method(方法)

clearBySign(sign:String):void ,[static] 清除物件池的物件。

Pool

getItem(sign:String):* ,[static] 根據傳入的物件型別標識字元,獲取物件池中已儲存的此型別的一個物件,如果物件池中無此型別的物件,則返回 null 。

Pool

getItemByClass(sign:String, cls:Class):*

[static] 根據傳入的物件型別標識字元,獲取物件池中此型別標識的一個物件例項。 當物件池中無此型別標識的物件時,則根據傳入的型別,建立一個新的物件返回。

Pool

getItemByCreateFun

(sign:String, createFun:Function):*

[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清空             
		}
	}
}

示例使用的圖片資源: