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 用于创建该类型对象的类.@return 此类型标识的一个对象
			 */
			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清空             
		}
	}
}

示例使用的图片资源:

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/86150096