0.如果你做了一个图集是1024X1024的。此时你的界面上只用了图集中的一张很小的图,那么很抱歉1024X1024这张大图都需要载入你的内存里面,1024就是4M的内存,如果你做了10个1024的图集,你的界面上刚好都只用了每个图集里面的一张小图,那么再次抱歉你的内存直接飙40M。意思是任何一个4096的图片,不管是图集还是texture,他都占用4*4=16M?
1、顶点性能
一般来说,如果您想在iPhone 3GS或更新的设备上每帧渲染不超过40,000可见点,
那么对于一些配备 MBX GPU的旧设备(比如,原始的 iPhone,如 iPhone 3g和 iPod Touch第1和第2代)来说,你应该保证每帧的渲染顶点在10000以下。
2、光照性能
像素的动态光照将对每个受影响的像素增加显著的计算开销,并可能导致物体会被渲染多次。
为了避免这种情况的发生,您应该避免对于任何单个物体都使用多个像素光照,并尽可能地使用方向光。
需要注意的是像素光源是一个渲染模式(Render Mode)设置为重要(Important)的光源。
像素的动态光照将对顶点变换增加显著的开销。所以,应该尽量避免任何给定的物体被多个光源同时照亮的情况。
对于静态物体,采用烘焙光照方法则是更为有效的方法。
3、角色
每个角色尽量使用一个Skinned Mesh Renderer,这是因为当角色仅有一个 Skinned Mesh Renderer 时,
Unity 会使用可见性裁剪和包围体更新的方法来优化角色的运动,而这种优化只有在角色仅含有一个 Skinned Mesh Renderer时才会启动。
角色的面数一般不要超过1500,骨骼数量少于30就好,角色Material数量一般1~2个为最佳。
4、静态物体
对于静态物体定点数要求少于500,UV的取值范围不要超过(0,1)区间,这对于纹理的拼合优化很有帮助。
不要在静态物体上附加Animation组件,虽然加了对结果没什么影响,但是会增加CPU开销。
5、摄像机
将远平面设置成合适的距离,远平面过大会将一些不必要的物体加入渲染,降低效率。
另外我们可以根据不同的物体来设置摄像机的远裁剪平面。Unity 提供了可以根据不同的 layer 来设置不同的 view distance ,
所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,
另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。
6、DrawCall
尽可能地减少 Drawcall 的数量。 IOS 设备上建议不超过 100 。
减少的方法主要有如下几种: Frustum Culling ,Occlusion Culling , Texture Packing 。 Frustum Culling 是 Unity 内建的,我们需要做的就是寻求一个合适的远裁剪平面;
Occlusion Culling ,遮挡剔除, Unity 内嵌了 Umbra ,一个非常好 OC 库。
但 Occlusion Culling 也并不是放之四海而皆准的,有时候进行 OC 反而比不进行还要慢,
建议在 OC 之前先确定自己的场景是否适合利用 OC 来优化; Texture Packing ,或者叫 Texture Atlasing ,
是将同种 shader 的纹理进行拼合,根据 Unity 的 static batching 的特性来减少 draw call 。
建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,
加大内存带宽的负担。这也就是为什么会出现“ DrawCall 降了,渲染速度也变慢了”的原因。
7.1.粒子系统运行在iPhone上时很慢,怎么办?
答:iPhone拥有相对较低的fillrate 。
如果您的粒子效果覆盖大部分的屏幕,而且是multiple layers的,这样即使最简单的shader,也能让iPhone傻眼。
我们建议把您的粒子效果baking成纹理序列图。
然后在运行时可以使用1-2个粒子,通过动画纹理来显示它们。这种方式可以取得很好的效果,以最小的代价。
优化:
1. 更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种,
每家的GPU支持不同的压缩格式,但他们都兼容ETC格式,
2. 对于透明贴图,我们只能选择RGBA 16bit 或者RGBA 32bit。
3. 减少FPS,在ProjectSetting-> Quality中的
VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
这两种情况都不符合游戏的FPS的话,我们需要手动调整FPS,首先关闭垂直同步这个功能,然后在代码的Awake方法里手动设置FPS(Application.targetFrameRate = 45;)
降低FPS的好处:
1)省电,减少手机发热的情况;
2)能都稳定游戏FPS,减少出现卡顿的情况。
4. 当我们设置了FPS后,再调整下Fixed timestep这个参数,
这个参数在ProjectSetting->Time中,目的是减少物理计算的次数,来提高游戏性能。
5. 尽量少使用Update LateUpdate FixedUpdate,这样也可以提升性能和节省电量。
多使用事件(不是SendMessage,使用自己写的,或者C#中的事件委托)。
6. 待机时,调整游戏的FPS为1,节省电量。
7. 图集大小最好不要高于1024,否则游戏安装之后、低端机直接崩溃、原因是手机系统版本低于2.2、超过1000的图集无法读取、导致。
2.2 以上没有遇见这个情况。
注意手机的RAM 与 ROM、小于 512M的手机、直接放弃机型适配。
VSCount 垂直同步
unity3d中新建一个场景空的时候,帧速率(FPS总是很低),大概在60~70之间。
一直不太明白是怎么回事,现在基本上明白了。我在这里解释一下原因,如有错误,欢迎指正。
在unity3D中当运行场景打开Profiler的时候,我们会看到VSync 这一项占了很大的比重。
这个是什么呢,这个就是垂直同步,稍后再做解释。
我们可以关闭VSync来提高帧速率,选择edit->project settings->Quality。
这就关闭了VSync(垂直同步),现在在运行场景看看,帧速率是不是提高很多。
现在来说说什么是垂直同步,要知道什么是垂直同步,必须要先明白显示器的工作原理,
显示器上的所有图像都是一线一线的扫描上去的,无论是隔行扫描还是逐行扫描,
显示器都有两种同步参数——水平同步和垂直同步。
什么叫水平同步?什么叫垂直同步?
垂直和水平是CRT中两个基本的同步信号,水平同步信号决定了CRT画出一条横越屏幕线的时间,
垂直同步信号决定了CRT从屏幕顶部画到底部,再返回原始位置的时间,
而恰恰是垂直同步代表着CRT显示器的刷新率水平。
为什么关闭垂直同步信号会影响游戏中的FPS数值?
如果我们选择等待垂直同步信号(也就是我们平时所说的垂直同步打开),
那么在游戏中或许强劲的显卡迅速的绘制完一屏的图像,但是没有垂直同步信号的到达,
显卡无法绘制下一屏,只有等85单位的信号到达,才可以绘制。
这样FPS自然要受到操作系统刷新率运行值的制约。
而如果我们选择不等待垂直同步信号(也就是我们平时所说的关闭垂直同步),那么游戏中作完一屏画面,
显卡和显示器无需等待垂直同步信号就可以开始下一屏图像的绘制,自然可以完全发挥显卡的实力。
但是不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面更加平滑和稳定。
取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上势必打折扣。
这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因。
合并材质球unity 3d中每倒入一次模型就多一个材质球,可我的这些模型都是共用一张贴图的就想共用一个材质球,所以每次都要删除再附上,很麻烦。怎么才能合并这些材质球?
采用TexturePacking吧
1、遍历gameobject,取出material,并根据shader来将material分类
2、调用Unity自带的PackTextures函数来合并每个shader分类中的material所对应的textures(PackTextures函数有缺陷,不过可以将就用)
3、根据合并的大的texture来更新原有模型的texture、material已经uv坐标值。
需要注意的是:需要合并的纹理应该是物体在场景中距离相近的,如果物体在场景中的距离较远,
则不建议合并纹理,因为这样做很有可能非但起不到优化的作用,反而降低了运行效率。
======================分割线==================
2-3个
小于30个
300-1500
这是因为角色的动作大多数都是事先设定好的,并不需要经过IK操作来进行实时计算(Rogdoll除外),所以在模型导入时,不要将IK结点一起导入。
2、静态实体
在静态实体上附加Animation部件虽然对结果没有影响,但却会增加一定的CPU开销来调用这一组件,所以尽量去掉该组件。
小于500
尽量保证UV值不越界,这对于将来的纹理拼合优化很有帮助。
3、地形
长宽均尽量小于257。这是因为地形太大,会造成大量顶点数据,给你的内存带宽造成一定的影响,在目前的ios设备中,内存带宽是非常有限的,需要尽量节省。同时,如果用Unity自带的地形,一定也要使用Occlusion Culling,因为Unity的刷地形工具虽然方便,但却是framekiller,刷过之后,你会发现drawcall增加的非常多。
不要超过4。地形的混合操作是很耗时的,应该尽量避免。能合并的纹理尽量合并。
4、纹理
建议png或tga。不用转成ios硬件支持的PVRTC格式,因为Unity在发布时会帮你自动转的。
长宽小于1024。同时应该尽可能地小,够用就好,以保证纹理对内存带宽的影响达到最小。
建议生成Mipmap。虽然这种做法会增加一些应用程序的大小,但在游戏运行时,系统会根据需求应用Mipmap来渲染,从而减少内存带宽。
如果纹理的alpha通道均为1,则用RGB的24位纹理来代替RGBA的32位纹理。(据说Unity内部会进行自动检测)
5、光源
建议1个,一般为方向光。“Important”个数应该越小越少。个数越多,drawcall越多。
1-2个。
6、粒子特效
建议小于200个粒子。
建议不超过50个。
如果可以的话,粒子的size应该尽可能地小。因为Unity的粒子系统的shader无论是alpha test还是alpha blending都是一笔不小的开销。同时,对于非常小的粒子,建议粒子纹理去掉alpha通道。
非常耗时。
7、音频
使用.ogg或.mp3的压缩格式。
使用.wav和.aif的未压缩音频格式。
8、相机
将远平面设置成合适的距离。远平面过大会将一些不必要的物体加入渲染,降低效率。
Unity提供了可以根据不同的layer来设置不同的view distance,所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。
9、碰撞
如果可以的话,尽量不用MeshCollider,以节省不必要的开销。如果不能避免的话,尽量用减少Mesh的面片数,或用较少面片的代理体来代替。
10、其他
尽可能地减少Drawcall的数量。IOS设备上建议不超过100。减少的方法主要有如下几种:Frustum Culling,Occlusion Culling,Texture Packing。Frustum Culling是Unity内建的,我们需要做的就是寻求一个合适的远裁剪平面;Occlusion Culling,遮挡剔除,Unity内嵌了Umbra,一个非常好OC库。但Occlusion Culling也并不是放之四海而皆准的,有时候进行OC反而比不进行还要慢,建议在OC之前先确定自己的场景是否适合利用OC来优化;Texture Packing,或者叫Texture Atlasing,是将同种shader的纹理进行拼合,根据Unity的static batching的特性来减少draw call。建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,加大内存带宽的负担。这也就是为什么会出现“DrawCall降了,渲染速度也变慢了”的原因。
Unity在运行时会对static物体进行自动优化处理,所以应该尽可能将非运行实体勾上static标签。
尽可能地使用prefab的实例化物体,以降低内存带宽的负担。检查实体的PrefabType,尽量将其变成PrefabInstance,而不是ModelPrefabInstance。
================分割线===============
移动平台相对于PC机,具有体积小,计算弱,带宽少的特点。
因此做手机游戏的开发,优化的方向,与力度对比PC游戏都有所区别。
必须要做到优化流程,合理利用资源。
目前在手机上面,还不能够像PC游戏那样追求高质量渲染效果,为了让手机不那么容易发烫,还要控制cpu,gpu,不能让他们全速运算。
材质方面:
纹理方面,建议使用压缩纹理,
android上面使用ETC1,苹果上面使用PVRTC。
UV坐标控制在0到1之间,人物模型面数控制在1500内,骨骼控制在30个以内。
场景中使用一个主光(不能再多了)。
尽量减少alphaTest和alphaBlend材质的使用。在手机上,这是很杀效率的。
骨骼动画方面:
在动画方面可以考虑不使用插值,固定的帧率的动画。
如果要做插值,考虑使用四元数(表示旋转)和向量(表示位移)来做插值。
四元数做插值速度比矩阵来的快,Slerp提供了平滑插值。
================分割线===============在美术制作场景的过程中,会使用到大量的粒子系统。
比如场景中的火把。在我们的一个地下城场景中,美术们放置了大量的火把。整个场景中的各个地方,有100来个火把。
unity中,在摄像机范围外的粒子系统虽然不会被绘制。
但是update是一直持续的。这也就意味着,这100多个火把,不论是否可见都在更新。
这个设计应该是很不合理的,在我看过的其他引擎中,都会有一个开关,来控制不可见的粒子系统是否需要update。
有的粒子系统在不可见的时候需要更新,比如爆炸。有的不需要更新,比如火堆火把。
为了避免不必要的update开销,尤其是最后游戏是要发布到页游平台(web player只能使用一个cpu的核)。
于是写了一个脚本,控制不可见的粒子系统就不更新。
该脚本主要是用到了2个MonoBehaviour的函数。
OnBecameInvisible() 当变为不可见 和 OnBecameVisible() 当变成可见。
要这2个函数起作用的前提是,该GameObject绑定了MeshRender组件。
所以,我们要在粒子系统的GameObject放置在一个GameObject 下,且给该GameObject绑定一个MeshRender 与 MeshFilter。
MeshFilter中的mesh可以随便找个cube。
在Start() 的时候,把最GameObject的scale设置为很小,以保证该cube不被看见。
其实遍历所有的child,把active设置为false。
在OnBecameVisible 中 遍历所有child,把active设置为true。
在OnBecameInvisible中 遍历所有child,把active设置为false。
整理资源来至 :http://www.manew.com/thread-21597-1-1.html
http://www.manew.com/thread-90138-1-1.html