- 试试把gameobject 一个一个禁用,确定下什么最影响性能
- stats 里面有多少个 Draw calls & 三角形
- 合并网格物体
- 合并材质张数
- 不要用网格碰撞.
- Unity对带动作的模型渲染消耗比较大,如果是静态的不带动作文件的模型渲染不会出现效率问题,但是要确保只绘制屏幕内的东西
1. 尽量避免每帧处理
比如:
function Update() { DoSomeThing(); }
可改为每5帧处理一次:
function Update() { if(Time.frameCount % 5 == 0) { DoSomeThing(); } }
2. 定时重复处理用 InvokeRepeating 函数实现
比如,启动0.5秒后每隔1秒执行一次 DoSomeThing 函数:
function Start() { InvokeRepeating("DoSomeThing", 0.5, 1.0); }
3. 优化 Update, FixedUpdate, LateUpdate 等每帧处理的函数
函数里面的变量尽量在头部声明。
比如:
function Update() { var pos: Vector3 = transform.position; }
可改为
private var pos: Vector3; function Update(){ pos = transform.position; }
4. 主动回收垃圾
给某个 GameObject 绑上以下的代码:
function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }
5. 运行时尽量减少 Tris 和 Draw Calls
预览的时候,可点开 Stats,查看图形渲染的开销情况。特别注意 Tris 和 Draw Calls 这两个参数。
一般来说,要做到:
Tris 保持在 7.5k 以下
Draw Calls 保持在 20 以下
6. 压缩 Mesh
导入 3D 模型之后,在不影响显示效果的前提下,最好打开 Mesh Compression。
Off, Low, Medium, High 这几个选项,可酌情选取。
7. 避免大量使用 Unity 自带的 Sphere 等内建 Mesh
Unity 内建的 Mesh,多边形的数量比较大,如果物体不要求特别圆滑,可导入其他的简单3D模型代替。
8. 优化数学计算
比如,如果可以避免使用浮点型(float),尽量使用整形(int),尽量少用复杂的数学函数比如 Sin 和 Cos 等等。
1、 ArrayList的对象在使用时应该注意以下事项
使用
arraylen = myarray. length;
for (i=0; i< arraylen; i++)
{
}
避免
for (i=0; i<myarray.length; i++) {
}
2、 少用临时变量
使用
var touch:Vector2;
function Update(){
if (count==0) { touch=iPhone.GeTouch(0).position;}
}
避免
function Update(){
if (count==0) {
var touch:Vector2=iPhone.GeTouch(0).position;
}
}
3、 少用算数符号/,改为乘以相应小数
使用
x * 0.5f
避免
x/2
4、 动作和AI不需要每帧都执行
if (GLO.count%3){
// execute the enemy aim at your player every 3 Update
}
if (GLO.count%5){
// execute player IA every 5 Update
}
5、 Mesh部分
原文:
- do not use several materials for one mesh. I got the problem with a little model that had 2 materials. It was taking 2 time more polys! When i removed one material, it was showing at half his the size. I don't know why. Usually each material = 1 draw call, so use texture atlas!
个人译文:
-对于一个mesh不要使用多张materials。我遇到过这样的问题是一个小模型拥有2张materials导致了2倍甚至更多的时间!而当我减少一个material的时候,时间减少了一半。
原文
- Use polygon cruncher to lower your mesh polys but even if your mesh look a little square, you can compensate this by tweaking "smoothing angle" in the importer inspector. For a highly optimized mesh, change the smoothing angle to 80 or even 120 and you mesh will look more smooth even with just a few polygons.
个人译文:
使用多边形粉碎机降低你mesh的面熟,但是虽然你的mesh看起来像一个正方形。你可以通过调整在导入区的” smoothing angle”选项来进行补偿。对于一个高优化的mesh,调整平滑角度到80甚至120度,你的mesh将看起来很配合虽然只是一点点的数量(???)
原文
- try not to use any expensive arithmetic like sin() or cos(). instead fill an array with precalculated values with x=0 to 360) sin(x) and cos(x) and use the values of this table. Of course it is in the case of you don't need precision.
个人译文
不要尝试使用任何昂贵消耗的数学公式,例如sin() 或 cos(),用预定义好的0到360度的sin(x)和cos(x)的值组成链表来替代。当然了前提是你不需要太精确。
原文
- force integer when possible. If you have a counter or check the position on the screen, declare the variable as INT, they are faster.
个人译文
尽可能的使用整形。如果你有一个检测屏幕位置的变量或者一个计数器,定义成整形会更快。
Unity3d的一些小窍门
1、防止黑屏
In script change iPhoneSettings.screenCanDarken to false. This basically does the same as:
//Objective-C call [UIApplication sharedApplication].idleTimerDisabled = YES;
It prevents the auto lock on iPhone to kick-in.
---------------------------------------------------
最近一段时间一直在做Unity 在IOS设备上的资源优化,结合Unity的官方文档以及自己遇到的实际问题,我把自己认为一些重要的信息罗列在下面,并尽可能对将其量化,以方便更多需要做优化的朋友。
1、 角色
-
每个角色尽量使用一个 Skinned Mesh Renderer
这是因为当角色仅有一个 Skinned Mesh Renderer 时, Unity 会 使用可见性裁剪和包围体更新的方法来优化角色的运动,而这种优化只有在角色仅含有一个Skinned Mesh Renderer 时才会启动。
- 角色 Material 数量
2-3 个
- 骨骼数量
小于 30 个
- 面片数量
300-1500
- 一般角色应该没有 IK 结点
这是因为角色的动作大多数都是事先设定好的,并不需要经过 IK 操作来进行实时计算( Rogdoll 除外),所以在模型导入时,不要将 IK 结点一起导入。
2、 静态实体
- 不要附加 Animation Component
在静态实体上附加 Animation 部件虽然对结果没有影响,但却会增加一定的 CPU开销来调用这一组件,所以尽量去掉该组件。
- 网格顶点数
小于 500
- UV 值范围尽量不要超过( 0, 1 )区间
尽量保证 UV 值不越界,这对于将来的纹理拼合优化很有帮助。
3、 地形
- 地形的分辨率大小
长宽均尽量小于 257 。这是因为地形太大,会造成大量顶点数据,给你的内存带宽造成一定的影响,在目前的 ios 设备中,内存带宽是非常有限的,需要尽量节省。同时,如果用 Unity 自带的地形,一定也要使用 Occlusion Culling ,因为 Unity 的刷地形工具虽然方便,但却是 framekiller ,刷过之后,你会发现 drawcall 增加的非常多。
- 混合纹理数量
不要超过 4 。地形的混合操作是很耗时的,应该尽量避免。能合并的纹理尽量合并。
4、 纹理
- 纹理格式
建议 png 或 tga 。不用转成 ios 硬件支持的 PVRTC 格式,因为 Unity 在发布时会帮你自动转的。
- 纹理尺寸
长宽小于 1024 。同时应该尽可能地小,够用就好,以保证纹理对内存带宽的影响达到最小。
- 支持 Mipmap
建议生成 Mipmap 。虽然这种做法会增加一些应用程序的大小,但在游戏运行时,系统会根据需求应用 Mipmap 来渲染,从而减少内存带宽。
- 检查 Alpha 值
如果纹理的 alpha 通道均为 1 ,则用 RGB 的 24 位纹理来代替 RGBA 的 32 位纹理。(据说 Unity 内部会进行自动检测)
5、 光源
- 光源“ Important ”个数
建议 1 个,一般为方向光。“ Important ”个数应该越小越少。个数越多, drawcall越多。
- Pixel Light 数目
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
如果可以的话,尽量不用 MeshCollider ,以节省不必要的开销。如果不能避免的话,尽量用减少 Mesh 的面片数,或用较少面片的代理体来代替。
10、 其他
- 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 降了,渲染速度也变慢了”的原因。
- 非运动物体尽量打上 Static 标签
Unity 在运行时会对 static 物体进行自动优化处理,所以应该尽可能将非运行实体勾上 static 标签。
- 场景中尽可能地使用 prefab
尽可能地使用 prefab 的实例化物体,以降低内存带宽的负担。检查实体的PrefabType ,尽量将其变成 PrefabInstance ,而不是 ModelPrefabInstance 。
备注: 优化是个无止境的过程, 可优化的项目其实还有很多很多,比如脚本优化,shader优化等等,这些留待以后再慢慢添加。
---------------------------------- 尽量控制定点数量(注意所谓顶点不是建模时的顶点,而是引擎渲染时的顶点。例如,模型一个顶点如果设置了2个法向,那么对引擎来说就是2个顶点) :
- 对Iphone3或更高设备,每帧渲染的顶点不超过4万个
- 对更早的设备,每帧渲染的顶点不超过1万个
- 场景所用的材质尽量减少。即使是不同的物件,也尽量采用同一个材质。
- 将固定的场景物件设置为静态(static)。
- 尽量使用PVRTC(这是Apple推荐的一种格式)纹理,不行的话,也尽量用16位纹理取代32位的。
- 不要在shader中使用multi-pass,通过用混合或者像素shader来合并不同的纹理以达到相同效果。
- 如果自行编写shader,尽量避免使用浮点数。下面是建议的类型:
- fixed/lowp——适用于颜色,光照等
- half/mediump——适用于纹理UV
- float/highp——避免在像素shader里使用,可以在顶点shader里面用于计算顶点位置
- 在像素shader中尽量少用复杂的数学计算,例如幂函数、三角函数等。
- 没必要的话不要使用像素光照(Pixel Lights)
- 不要使用动态光照,用烘焙的lightmap
- 不要使用alpha测试,用alpha混合来代替
- 不要使用雾
- 大场景中使用Occlusion culling来削减不可见区域。关卡设计时考虑到实施 Occlusion culling 的便利性
- 使用sky box 来实现远景
- Keep vertex count below:
- 40K per frame when targeting iPhone 3GS and newer devices (with SGX GPU)
- 10K per frame when targeting older devices (with MBX GPU)
- Keep the number of different materials per scene low - share as many materials between different objects as possible.
- Set Static property on a non-moving objects to allow internal optimizations.
- Use PVRTC formats for textures when possible, otherwise choose 16bit textures over 32bit.
- Use combiners or pixel shaders to mix several textures per fragment instead of multi-pass approach.
- If writing custom shaders, always use smallest possible floating-point types:
- fixed / lowp -- perfect for color, lighting information and normals,
- half / mediump -- for texture UV coordinates,
- float / highp -- avoid in pixel shaders, fine to use in vertex shader for vertex position calculations.
- Minimize use of complex mathematical operations such as pow, sin, cos etc in pixel shaders.
- Do not use Pixel Lights when it is not necessary -- choose to have only a single (preferably directional) pixel light affecting your geometry.
- Do not use dynamic lights when it is not necessary -- choose baking lighting instead.
- Choose to use less textures per fragment.
- Avoid alpha-testing, choose alpha-blending instead.
- Do not use fog when it is not necessary.
- Learn benefits of Occlusion culling and use it to reduce amount of visible geometry and draw-calls in case of complex static scenes with lots of occlusion. Plan your levels to benefit from Occlusion culling.
- Use skyboxes to "fake" distant geometry.