Starling 性能优化方案
转自:http://www.starlinglib.com/wiki/StarlingManual:PerformanceOptimization
二转:http://www.cnblogs.com/sevenyuan/archive/2013/01/10/2854406.html
性能优化
虽然Starling模仿了Flash传统显示列表,但您要知道屏幕背后发生的事情是有很大不同的。要得到应用的最佳性能,您需要了解关于Starling体系结构的一些关键概念。下面是一些您可以遵循的,让您的游戏尽可能的快速的最佳实践。
尽可能减少状态变更
如您所知,Starling使用Stage3D来渲染所有的可见对象。这就意味着所有的绘制都是GPU完成的。
现在,Starling可以一个接一个的发送四边形到GPU,然后一个接一个的绘制。实际上,这也是最初版本的Starling的工作方式。然而,为了更好的执行效率,GPU希望能得到大量的数据,然后在一次调用中绘制所有的对象。
这也是为什么Starling的最新版本要在发送数据到GPU之前要包含尽可能多的四边形。然而它只能批量处理那些拥有相似属性的四边形。每当遇到一个具备不同“状态”的四边形,就会触发“状态改变”,上一个批次的四边形就会被绘制。
这篇文章中,我将使用“Quad”和“Image”来代表相似的概念。请记住,Image只是Quad的一个添加了纹理的子类。
下面这些是促使状态发生改变的关键特性:
- 纹理 (虽然从相同的图集中获得不同的纹理是可以的)
- 显示对象的混合模式
- 图片的平滑设置
- 纹理的平铺模式
- 四边形的着色属性 (下面提到的)
如果您可以用一种尽可能减少状态变化的方式创建场景,那么您的渲染性能将会受益无穷。
着色四边形
一些移动设备硬件(比如第一代的iPad)处理纹理的“着色”时非常困难,包括:
- 用半透明的方式去绘制它们(alpha值是其中之一)
- 用不同的颜色来绘制(设置image.color等于一些不是白色的色值)
由于这个原因,Starling优化了未着色的图片的渲染代码。但这样带来了一个缺点:在未着色的对象和着色的对象之间切换时,将会导致一次状态变更。在您设置图片的颜色或透明度的时候,请牢记这一点。
如果您创建了一个硬件加速的游戏,并且没有考虑到着色这个问题,那么这些状态变更可能给您的性能带来不必要的麻烦。
这里有个简单的技巧来避免状态变更:只需要设置您的根对象(root object)的透明度为“0.999”或一个近似的值。由于这个透明度会向下影响到子元件的渲染,Starling会将任何对象都按照“着色”对象来对待,这样就不会触发过多的状态的变更了。
画家算法
要了解如何尽量减少状态变更,您需要了解Starling处理您的对象的顺序。
和传统Flash类似,Starling也采用了一种“画家算法”来处理显示列表。这个算法的意思就是,就像一个画家所做的那样,来绘制您的场景:首先绘制最底部的对象(比如一个图片背景),然后再绘制上一层的对象(以此类推)。
如上图所示,如果您想在Starling中创建这样的场景,您可以创建3个Sprite容器:一个用来包含远处的山脉,一个包含地面,一个包含植被。山脉的排序肯定在最底部(索引是0),植被的排序是在最顶部(排序是2)。每一个Sprite会包含有实际内容的图片。
在渲染的时候,Starling会先渲染最左侧的"Mountain 1",并向右继续渲染,直到到达 “Tree 2”。现在,如果所有的对象都有不同的状态,那么就会造成6次绘制调用。如果您从每一个单独的图像来加载每一个对象的纹理,就会发生这样的情况。
纹理图集
这就是纹理图集是如此重要的原因之一。如果从一个单一的图集加载所有这些纹理,Starling就可以在一次调用中完成所有的绘制! (假如上面列出的其他属性没有改变的话。)
在这里,每个图像都使用相同的图集(用所有节点具有相同的颜色来表示)。这样的后果就是您应该总是让您的所有纹理使用同一个纹理图集。
然后,有时候,并非所有的纹理都能融合到一个单一的图集上。一个纹理图集的限制是2048*2048像素(这是一些移动设备硬件的限制),所以您早晚都会碰到这种所需纹理为空的情况。但是这也没什么问题---只要您用一种聪明的方式来安排您的纹理。
如上图所示,这两个例子都是使用了两个纹理图集(同样,每一个纹理图集用一个颜色表示)。但是左侧的显示列表,将强迫每个对象发生状态改变,而右侧的版本则可以只需要两次批处理就能绘制所有的对象。
扁平化的Sprites
通过减少状态变更,您已经让您的游戏性能得到了极大改善。然而,Starling还是需要遍历所有的对象,检查它们的状态,然后上传它们的数据到GPU---在每一帧都是如此。
这是下一步优化要做的内容。如果您的游戏中有一些内容是静态的,并且不会发生(或很少)改变,就可以调用这个Sprite容器的flatten方法(暂且翻译为扁平化吧)。Starling将会预处理它的子元件,并上传它们的数据到GPU。在后续的帧中,它们就可以马上被呈现,而且不需要任何额外的GPU处理,也无需向GPU上传新的数据。
这是一个强大的特性,可以极大地减少CPU的负载。您只需注意,每一个扁平化的容器,仍然会被状态变化影响:如果一个扁平化容器的几何数据包含了一些不同的渲染状态,它仍然会在多个步骤进行绘制。
QuadBatch 类
扁平化的容器非常快速和容易使用。然而,它们仍然有一些开销:
- 当您在Sprite上添加了一个对象,它们将派发"ADDED"和"ADDED_TO_STAGE"事件,如果有很多子元件需要添加,这可能也是不小的开销。
- 对于任何的显示对象容器来说,一个特定的子元件只能添加一次。
为了摆脱这些限制,您可以去使用Starling的一个底层类:QuadBatch。它的工作原理是这样的:
var quadBatch:QuadBatch = new QuadBatch(); var image:Image = new Image(texture); quadBatch.addImage(image);for (var i:int=0; i<100; ++i) {image.x += 10;quadBatch.addImage(image); }
您是不是已经注意到了?如果您愿意,您可以重复添加相同的图像!此外,它不会引发任何事件调度。然而事务都有两面性,这样做也有一些缺点:
- 您添加的所有的对象必须具备相同的状态(比如:使用同一个纹理图集)。您添加到QuadBatch的第一个图像决定了它的状态。您不能再改变状态,除非完全重置这个QuadBatch。
- 您只能添加Image, Quad, 或 QuadBatch类的实例.
- 这是一条单行道:您只能添加对象。删除一个对象的唯一途径是重置当前批次。
由于这些原因,它仅适用于一些特定的场景(比如位图字体类,就直接使用了四边形批次)。在这些情况下,它肯定是最快的选择。您将找不到一个更有效的方式来呈现Starling对象。
使用位图字体(中文只能用True Type,不考虑)
文本框支持两种不同的字体:True Type字体和位图字体。
TrueType字体最容易使用:只需嵌入所需的“ttf”文件,您就大功告成了。为静态文本框包含数百个字符,这是一个很好的和快速的选择。Starling会将文本渲染成位图,显示文本的时候就像一个纹理一样。对于重复改变的短文本(比如分行显示),这样处理还是挺慢的。
如果您的游戏需要显示的文本中包含许多非ASCII字符(如中文或阿拉伯文),TrueType字体可能是您唯一的选择。位图文本只是受限于它们的纹理大小。
使用位图字体的文本框,创建和更新都是非常快速的。另一个优点是,它们不会占用任何额外的纹理内存,除了它们所需的原始纹理。这是在Starling中显示文本的首选方式,我的建议是尽可能的使用它们。
使用BlendMode.NONE
如果您有完全不透明的矩形纹理,可以帮助GPU禁用那些纹理混合。这对于大背景图像特别有用。不要害怕这将导致额外的状态变化,这是值得的!
backgroundImage.blendMode = BlendMode.NONE;
使用Stage.color
如果您的游戏背景是一个单独的颜色,请设置stage的颜色来代替添加一个纹理或一个着色的四边形。反正Starling每一帧都要做stage的清理工作---如果您改变了stage的颜色,那么也没有额外的消耗。这简直就是免费的午餐哦,记得享用。
[SWF(backgroundColor="#ff2255")] public class Startup extends Sprite {// ... }
避免重复调用width和height
获取宽度和高度属性是一个昂贵的性能开销,特别是对于Sprite容器(首先矩阵进行计算,然后每一个子元件的每个顶点都和该矩阵相乘)。
出于这个原因,请避免重复访问它们,比如在一个循环里面。在某些情况下,使用一个恒定的值来代替它们更有意义。
// 坏方案: for (var i:int=0; i<numChildren; ++i) {var child:DisplayObject = getChildAt(i);if (child.x > wall.width)child.removeFromParent(); }// 好方案: var wallWidth:Number = wall.width; for (var i:int=0; i<numChildren; ++i) {var child:DisplayObject = getChildAt(i);if (child.x > wallWidth)child.removeFromParent(); }
让容器不可点击
当您在屏幕上移动您的光标/手指的时候,Starling就会寻找哪一个对象被点击了。这可能是一项昂贵的操作,因为它需要遍历所有的显示对象,并调用hitTest方法。
因此,如果您不需要一个对象被触碰,将它设置为“untouchable”是非常有帮助的。最好是在容器上进行禁用:这样,Starling就不会遍历它的子元件。
// 好方案: for (var i:int=0; i<container.numChildren; ++i)containter.getChildAt(i).touchable = false;// 更好的方案: container.touchable = false;
使用新的事件模型
从Starling 1.2开始, 有一个新的方法来派发事件:
// 传统方式: object.dispatchEvent(new Event("type", bubbles));// 新方式: object.dispatchEventWith("type", bubbles);
就像第一个传统的方式那样,第二种方法也会派发一个事件对象,但是在屏幕背后,它会用对象池来缓存事件对象。这就意味着,如果您使用第二种方式,将会节省一些垃圾回收器工作的时间。由于它书写简练并且速度更快---因此,它是现在派发事件的首选方式。(如果您已经创建了Event类的子类,就不能用这个方法来派发事件)
ActionScript 指导
以下的优化方式是通用的(并不特指Starling),对于所有的ActionScript项目都是最佳实践。但是别太高估它们:您的首要任务是保证代码的优良结构和可读性。这些优化在一些每帧都调用的代码中最有效。
循环
避免“for each”. 用传统的 “for i”是最快的. 此外需要注意的是,将一些变量事先保存,在每次循环中调用,也是非常有用的。
// 慢的: for each (var item:Object in array) { ... }// 快的: for (var i:int=0; i<array.length; ++i) { ... }// 更快的: var length:int = array.length; for (var i:int=0; i<length; ++i) { ... }
避免创建对象
避免产生大量的临时对象。它们占用内存,并且需要由垃圾收集器进行清理,这可能会导致运行时的"卡壳"。
// 坏的: for (var i:int=0; i<10; ++i) {var point:Point = new Point(i, 2*i);doSomethingWith(point); }// 好的: var point:Point = new Point(); for (var i:int=0; i<10; ++i) {point.setTo(i, 2*i);doSomethingWith(point); }
访问数组或向量数组元素
当您从一个数组或一个向量数组中引用一个对象的时候,要小心:当对象索引是一个计算结果的时候,请转换为int类型。出于某种原因,这样可以让AS3计算更快。
// 坏的: var element:Object = array[10*x];// 好的: var element:Object = array[int(10*x)];
Starling 性能优化方案相关推荐
- starling性能优化
在项目开发的过程中总结了一下starling的性能优化方案: 1. 不要频繁的读取显示对象的宽高:调用宽高属性时会调用显示对象的getBounds()方法,该方法会遍历该对象的所有子对象,重新 ...
- Mysql性能优化方案
2019独角兽企业重金招聘Python工程师标准>>> 内容简介:这是一篇关于mysql 性能优化的文章.网上有不少mysql 性能优化方案,不过,mysql的优化同sql serv ...
- kvm性能优化方案---cpu/内存/磁盘/网络
kvm性能优化方案 kvm性能优化,主要集中在cpu.内存.磁盘.网络,4个方面,当然对于这里面的优化,也是要分场景的,不同的场景其优化方向也是不同的,下面具体聊聊这4个方面的优化细节. cpu 在介 ...
- 人人都能掌握的Java服务端性能优化方案
转载自 人人都能掌握的Java服务端性能优化方案 作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验.如果我们的代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响 ...
- react性能优化方案_React灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...
react性能优化方案 在我以前的文章中,我研究了一个虚拟的交易引擎,并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较. 在文章的结尾,我写道: 我怀疑随着Node.js的 ...
- 小猿圈web前端之网站性能优化方案
现在前端不仅要能做出一个网站页面,还要把这个页面做的炫酷,那需要很大程度的优化,那么怎么优化才更好呢?小猿圈总结了一下自己优化的方案,感兴趣的朋友可以看一下. 一般网站优化都是优化后台,如接口的响应时 ...
- mysql 性能优化方案
网 上有不少mysql 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...
- 用友u8服务器优化,用友U8erp软件运行的性能优化方案图文教程
今天一定要给大家分享一下用友U8erp软件运行的性能优化方案图文教程,以下方案来自用友软件官方维护工程师反馈在在处理客户问题的时候,有一类问题较为挠头,就是诸如用友U8服务器效率低下的问题.比如用友U ...
- 浅谈Android性能优化方案
经过前一阶段的调查,大概对性能优化已经有了初步的解决方案: 先给大家介绍一下UC公司的性能优化指标以及部分方案: 一.性能优化六项指标: 性能.内存.稳定性.流量.电量.安装包大小: 二.背景 --- ...
最新文章
- OpenCV中响应鼠标信息cvSetMouseCallback函数的使用
- Android Widget 中ListView加载网络图片
- 栈的应用--进制转换
- Vue.js 笔记之 img src
- [USACO19JAN,Platinum]Train Tracking 2
- LeakCanary,检测安卓,java内存泄漏
- 摄影基础知识:等效焦距是什么?
- abaqus切削为什么没有切屑_切削液降温6大绝招,肯定有一款适合你
- python 阿里云短信接口_阿里云短信接口怎么使用
- Android 自定义万能的抽屉布局(侧滑菜单)GenericDrawerLayout
- 基于javaswing实现PC端课堂点名程序详细设计
- 企业微信登录本地调试
- pyecharts绘制地图(Geo and Map)(细节更丰富)
- 2021-05-10
- java校园圈子论坛跳蚤市场小程序源码
- 儿童智能定位鞋方案/案列/APP/小程序/网站
- 一、线性模型----Lasso、Ridge回归及正则化的初步理解
- Mac缓解或关闭鼠标加速
- FFplay文档解读-16-音频过滤器一
- vue中的一个子组件如何在父组件中调动另一个子组件中的方法
热门文章
- vue中watch监听路由传来的参数变化
- Open3d之点云可视化
- java doget 返回json_HttpClient调用doGet、doPost、JSON传参及获得返回值
- 生成的头_谷歌新款怪物制造机,用GAN一键生成定制版哥斯拉
- SpringCloud实战五:统一配置中心
- 解决只能滑动弹框内容不能滑动弹框底层内容
- vue - (v-pre、v-cloak、v-once)
- lemon oa前端页面——由user-base-list谈项目组织
- DDD(Domain-Driven Design)领域驱动设计-(三)命令风暴寻找聚合
- 细数魅族metal电信版手机3宗罪。