[转] 擎天哥as3教程系列第二回——性能优化
所谓性能优化主要是让游戏loading和运行的时候不卡。
一 优化fla导出的swf的体积?
1, 在flash中,舞台上的元件最多,生成的swf越大,库里面有连接名的元件越多,swf越大。当舞台上没有元件且库里面的元件没有连接名的话生成的swf最小。
2, 一个flash动画有10帧,10帧上面全部是位图和用一个位图播放器播放这10张图片谁消耗的cpu更高?
答:flash动画播放消耗性能更高,因为swf文件里虽然也是位图,但是swf里面的播放机制是能播放位图,矢量图,声音,视频等。所以就算只播放位图的时候,依然会执行那些无用的代码。
3, 在flash中就算元件在舞台外面依然会使swf变大。
4, 在flash中对位图使用平滑可防止移动时抖动。
5, 在flash中对位图俺jpeg压缩时可按品质或者按导入的jpeg数据压缩,就算品质为100%也会小程度的压缩,如果按导入的jpeg数据压缩的话也会小程度压缩。无损压缩是完全没有压缩。
6, 帧代码行数越多生成的swf越大(但不是把两行代码合并成一行就可以节省内存)
7, 在flash中的帧上,即使不写任何代码但是如果每行只有空格的话也会增加生成swf的大小,代码的字数越多越占用内存,因为字母也要占内存的。
二 在flex 中如何减少主swf的大小?
1, 类库和ui不要包含到主swf里面,采用dll加载机制(运行时加载)。
具体做法如图:
连接类型都采用外部。这样就不会把代码包含到主swf里面。
把生成的dll文件在进入游戏的时候加载进去。
2, 主swf里面只包含基础加载条,基础背景这些基本的东西就行。
3,主swf所在的项目里不要有太多的类。因为这些类默认会包含进去的。
三 如何在loading的时候能够流畅的进行呢?
有的游戏的加载机制是很多个资源一块加载,导致加载的时候占用大量的贷款和性能,造成拥堵这样是很不科学的。
科学的方法是采用队列加载机制。把资源放到一个队列里面,一个一个加载,当然资源非常小的时候可以并发同时加载多个。这样加载起来就会很流畅。
四性能优化:
1, 选用合适的变量。如果是整整数就不要用Number,用uint或者int,如果是无符号的就用uint类型的。对于不用交互的显示对象就用Shap或者Bitmap,(shap实现了绘图API,Bitmap是表示位图的显示对象)。对于不需要时间轴的可交互对象请使用sprite否则使用MovieClip(注:Loader类也属于显示对象)
2, 最好不要在声明变量的地方直接赋值,这样会无谓增加内存的开销,因为在flashPlayer里面只声明变量只是会占用很少很少的内存开销(因为flashPlayer要保存他们的默认值)。如果初始化之后就会增加额外的开销,所以在需要的时候再初始化。
3, 请注意 uint,int的初始值为0 ;Number的初始值为NAN;string 的初始值为 null,其他已知类型的初始值均为null,位置类型的初始值为unidefinde。Uint ,int的默认内存为4字节,number默认内存为8字节
4, 重用对象
能用一个对象完成功能,就不要new出来多个对象。
比如:很多地方需要用到一个Point对象,你只需要new出一个point对象,然后在用的 改变它的x,y值就ok了。
5, 对象池机制
这个很重要,用的好了能极大的优化性能。
比如我有一个漂浮框的提升,你把所有new出的漂浮框对象全部放到两个列表里,一个列表存放正在用的对象,一个列表存放已经用过的对象。当你需要用的时候,先去判断空闲列表里是否有对象,有的话就直接取出来,没有的话就重新new出一个,然后再放到一个列表里。
又如地图里面需要不段的刷新出同一种怪物,你不要每次刷新怪物都new出一个新的怪物出来,把那些死的怪物重新初始化就行了。
6, 有效释放内存
flashPlayer垃圾回收机制采用的是标价清除,因为非基元变量之间传递的都是引用,当这个对象没有被任何变量引用的时候方才能被回收。
一般的做法是将变量设为null,并清除事件和引用。
怎么释放内存我将另外开辟一个章节介绍。
7 在bitmap和bitmapData中可以优化性能的地方。
首先要知道bitmapData中包含像素信息的数组,他表示位图图像的信息数据。
所以bitmapData的长宽设的越高,他所占用的内存就越高。
所以在做位图操作时记得要改变bitmapData的宽和高。
比如在做切换地图的时候,地图的尺寸是不大一样的,第一张地图的尺寸是800*600,你设置bitmapdata的宽高为800*600,第二张的地图尺寸是500*500,。那么你用800*600 尺寸去操作500*500的尺寸就是浪费。
另外记住这个几个方法
Dispose();这个是释放bitmapdata中的内存的。
Lock()是锁定图像,让bitmapData信息改变的时候引用此bitmapdata的图像不会改
变。这样可以节省性能。
Unlock();解锁图像。
使用setVector()绘制像素比setPixel(),setPixels()更高效
8,在movieChip中可以优化性能的地方。
movieClip是带有的时间轴的显示对象,即使你把mc移除的时候,正在运行的时间轴依然会占用cpu周期,所以要把movieClip回收的时候请停止其中的时 间轴。
9,在dictionary中可以优化性能的地方。
设置dictionary中的强引用为true,使用delete 清除字典里面的元素的引用,然后在 设置为null
{
Delete dic[obj]
Obj.destroy();
Obj = null;
}
10, 在arrary中可以优化性能的地方。
有时候把 arrary 设为null,只是把引用清掉,但里面的元素并没有销毁。
For each(var obj:* in arr)
{
Obj.destroy();
Obj = null;
}
Arr = null;
11动态类中变量删除的方法。
包括 Dictionary都可以用delete 删除引用。
12 尽量少使用滤镜
使用滤镜会生成一个栅格化的位图。
当修改位图的属性时,会同时更新原图和栅格化位图。会占用cpu
13 对于色彩要求度不高的可以使用8位或者16位的颜色通道。
14 事件派发和回调之间的权衡
根据flashPlayer的事件机制,会从主舞台轮询子对象,直到目标对象。
所以比较耗cpu和内存。使用回调函数速度更快,不需要创建event对象。
所以在使用事件时,如果对于不需要事件监听的对象可以禁止或设置他们子对象监听事件。Mc.mouseChildren = false;
mc.mouseEnable = false;
mc.enable = false;
15 flashPlayer 重绘机制
重绘就是,flashPlayer以一定的帧频刷新屏幕上显示内容。
什么时候重绘?
舞台上显示对象状态,形状,位置发生改变的时候。
层级发生改变
某些事件引起的重绘,比如在button上划过鼠标
减少重绘
将visible设为false,并不能停止重绘。应该停掉动画(包括子元件),最好是
移除掉。
显示对象移除舞台之外,改对象是不会重绘的。只是不会重绘,但里面的代码
逻辑等依然会占用cpu周期和内存。
设置DisplayObject的层级关系时候,先做判断,可以有一定概率改进性能
if (myContainer.getChildIndex(myChild) != 0)
{
myContainer.setChildIndex(myChild, 0);
}
当一个Sprite/MovieClip cacheAsBitmap = true,该对象已经被当做一个整体的重绘区域了,当它的某个区域(即使被遮盖了)发生变化,会导致整个Sprite/MovieClip发生重绘。一个改进是,将该变化区域用scrollRect 进行优化
对于设置了cacheAsBitmap = true 的元素,由于元素整体被缓存成了位图,当元素有变化时,缓存的位图也会变化,所以会引起元素的重绘,所以对于大小变形经常变化的显示元素最好不要用缓存位图,而且占内存。
16 scrollRect 和mask
使用mask或者scrollRect时看不见的区域一样在消耗CPU在渲染,必要时还是应该把在这些看不见的区域内的显示对象属性设置为 false.在一些游戏的滚屏中使用copyPixels而不要用scrollRect或mask.
17 位图缓存
使用位图缓存可以使显示对象以位图的形式呈现,进行重绘时直接可以以位图 的方式重绘。比如当MovieClip重绘时需要考虑到子对象的重绘以及帧什么的。 当使用位图缓存时就忽略掉了这些部分。但w位图缓存不能滥用。
何时用位图缓存?
当对象只是需要简单的平移,拖动的时候。或者静止的时候。内部不需要复杂的变化。
滚动文本字段,这个flash帮助上说的比较不容易理解。其实它的意思就是把需要滚动的文本框放到mc中,对mc使用scrollrect滚动,然后位图化mc。这样重绘的时候就不需要重绘整个textField了,因为已经位图化了。
窗口系统一般情况下面板类对象都是拖动,平移,不会有太多的变化。
何时避免使用位图?
位图化后的对象比源对象会占用更多的内存,启用表面只是提高了呈现性能。
对像太复杂的操作,比如旋转,缩放,翻转以及动画等不宜使用缓存。
位图缓存不要和矢量数据放到一块。
18 减少显示对象的嵌套。
显示里面的嵌套越多,flashPlayer就要耗费越大的性能去计算。 减少依靠父对象对子对象做操作,比如相当于父对象的定位。不仅要计算子对象还要计算父对象。
19 vector比array类访问速度更快。
20 var obj:object = {}; var arr:Array = []这样赋值会更有效率。
21 对textField对象请使用appedText()方法,不要使用+= 运算
在for循环中给textfield赋值请不要直接操作text,而是将值赋给
一个字符串,循环结束后再有字符串赋给text
22 避免直接使用中括号进行操作,而是将值赋给一个变量,然后对变量进行操作。
Arr[i].x = 100; 这样是错误的。
Var mc:* = Arr[i]; mc.x = 100; 这样是对的。
23 避免在循环中出现表达式
For (var i:uint = 0; I < arr.length; i++); 错误
Var length:uint = arr.lenth;
For(var i:uint = 0; I < length; i++) 对的。
错误的方法每次都要计算arr的长度
24 使用适当的舞台品质可以提高游戏流畅性。
StageQuality.LOW低呈现品质
25 使用alpha属性时避免使用alpha混合效果,列如淡化效果,alpha混合将占用flashPlayer 的大量处理资源,尽可能避免使用alpha属性。
27 选择合适的帧频。帧频越高耗费性能越大。
动态改变帧频
当没有动画内容的时候请将帧频改为1.
28 尽量使用位操作
比如 10 / 2,和 10 >> 1是等效的,但位操作速度更快。