unity优化



M aterial
每次求更改 material都会生成一个新的对象
Renderer.sharedMaterial
而是直接在原material   上修改  使用相同material的属性也会更改

静态批次
会将进行批次的多个对象合并成一个大的对象,也会导致内存损耗,有时候要避免太多对象静态批次造成的内存过高

动态批处理合并条件 (顶点数量,缩放大小,材质)
    1批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体。
     2如果你的着色器使用顶点位置,法线和UV值三种属性,那么你只能批处理300顶点以下的物体;如果你的着色器需要使用顶点位置,法线,UV0,UV1和切向量,那你只能批处理180顶点以下的物体。
     3不要使用缩放。分别拥有缩放大小(1,1,1) 和(2,2,2)的两个物体将不会进行批处理。
     4统一缩放的物体不会与非统一缩放的物体进行批处理。
     5使用缩放尺度(1,1,1) 和 (1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1) 和(1,3,1)的两个物体将可以进行批处理。
     6使用不同材质的实例化物体(instance)将会导致批处理失败。
     7拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一部分)。
     8多通道的shader会妨碍批处理操作。比如,几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道。
     9预设体的实例会自动地使用相同的网格模型和材质。
     10渲染次序也会也会影响
如果顺序为:
    1.渲染A,使用材质1
    2.渲染B,使用材质1
    3.渲染C,使用材质2
  那么drawcall是2个,AB进行了动态批次。
  如果顺序为:
    1.渲染A,使用材质1
    2.渲染C,使用材质2
    3.渲染B,使用材质1
那么drawcall就是3个,AB的批次被C打断了。
      解决方法
  1首先根据物件到摄像机的距离,进行远处物件先渲染近处物件后渲染。相同材质的物件尽量在一层,不要让不同材质的物件进入这一层。
  2 shader渲染队列,渲染队列小于等于2500时,unity认为其是不透明的,对于不同材质但z值相同对象,unity不对其进行排序,这样能保证相同材质的多个对象能是一个批次,不同材质的对象 如果进入两个相同材质的对象之间,不会打破批次;
     渲染队列大于2500时,unity会对不同材质的对象进行排序,此时如果不同材质的对象进入到两个相同材质的对象之间的话,会使相同材质的对象批次被打破。
     实时光照和阴影可能增加Drawcall,带有光源计算的shader材质会因为光照产生多个Drawcall。使用灯光会打断Drawcall batching。

Alpha Test
采用一种很霸道极端的机制,只要一个像素的alpha不满足条件,那么它就会被fragment shader舍弃,“我才不要你类!”。被舍弃的fragments不会对后面的各种Tests产生影响;否则,就会按正常方式写入到缓存中,并进行正常的深度检验等等,也就是说,Alpha Test是不需要关闭ZWrite的。Alpha Test产生的效果也很极端,要么完全透明,即看不到,要么完全不透明。
Alpha Blending
则是一种中庸的方式,它使用当前fragment的alpha作为混合因子,来混合之前写入到缓存中颜色值。但Alpha Blending麻烦的一点就是它需要关闭ZWrite,并且要十分小心物体的渲染顺序。如果不关闭ZWrite,那么在进行深度检测的时候,它背后的物体本来是可以透过它被我们看到的,但由于深度检测时大于它的深度就被剔除了,从而我们就看不到它后面的物体了。因此,我们需要保证物体的渲染顺序是从后往前,并且关闭该半透明对象的ZWrite。

NGUI
1 关闭贴图的读写选项
  Unity中导入的每张贴图都有一个启用可读可写(Read/Write Enabled)的开关,对应的程序参数是TextureImporter.isReadable。
2 UIPanel就需要重建这个控件所用的DrawCall, 尤其是将运行时会运动变化的UI控件和静止不变的UI控件的DrawCall合在了一起
3 NGUI中的东西,我们统一使用Depth来进行空间的划分

资源优化
模型优化
1. 每个模型只使用一个skinned mesh renderer
2. 每个mesh不要超过3个material
3. 骨骼数量不要超过30
4. 面数在1500以内将得到好的效率

Gpu 优化
目标
DrawCall数量:峰值 < 250,主体范围(5% - 95%)应在(0 - 200)个之内。
Triangle数量:峰值 < 100000/帧。
VBO上传量:峰值 < 5MB,频繁加载的资源使用缓存池缓存。
kinned Mesh数量:峰值 < 50,对应Profiler中的MeshSdinning.Update、Animator.Update。
RenderTexture:数量 < 10。  
PC 平台的话保持场景中显示的顶点数少于 200K~3M ,移动设备的话少于 10W
方法 
     特效
 1 特效尽量少使用粒子或者将粒子的数量减少到最小。
 2 特效没有将自身的Active属性设置为false,那么它就会继续占用你的DrawCall,消耗你设备的计算能力。
 3 特效尽量使用UV动画 不适用稠密的粒子。
 4 特效 不使用fog,使用渐变的面片(参考shadow gun)
shader
1 不使用或少使用动态光照,使用light mapping和light probes(光照探头)。可·
2 使用alpha-blend 代替 alpha test。
3 使用尽量少的material,使用尽量少的pass和render次数,如反射、阴影这些操作
4 如有必要,使用Per-Layer Cull Distances,Camera.layerCullDistances 提供了可以根据不同的 layer 来设置不同的可渲染物体范围
5 只使用mobile组里面的那些预置shader
6 shader中用贴图混合的方式去代替多重通道计算
7 shader中注意float/half/fixed的使用。
8 shader中不要用复杂的计算pow,sin,cos,tan,log等。
9 远处的物体绘制在skybox上
         贴图
1 合并图集。保证屏幕显示的资源使用的图集尽量少,屏幕显示不用还打包进去会占用内存和位宽起反效果。注意控制不要让图集太大,一个超级大图集的DrawCall消耗或许顶的上十几个小图集的消耗
2 如果使用了纹理图集和共享材质,使用Renderer.sharedMaterial 来代替Renderer.material 。 Renderer.sharedMaterial 使用的是同一个material的引用
3 OpenGL ES 2.0使用ETC1格式压缩等等,在打包设置那里都有。 贴图压缩格式:ios上尽量使用PVRTC,Android上使用ETC
4 使用mipmap。
         顶点
1尽量减少无用的顶点数据
2 使用LOD,好处就是对那些离得远,看不清的物体的细节可以忽略,用空间换时间
3尽量使用静态批次 减少动态批次修改模型数据
4用视口去掉不要的模型再渲染 

内存优化
目标
  建议总内存控制在150MB以下;堆内存控制在40MB以下。
     纹理内存占用过大:峰值 < 50MB。
     网格资源内存过大:峰值 < 20MB。
     动画片段:内存 < 15MB,
     音频资源:内存 < 15MB,
方法
unity (图片,声音,gameobject,物理,渲染器)
     1减少场景中的GameObject数量
       2尽量减少在Hierarchy对资源的直接引用,而是使用Resource.Load的方法,在需要的时候从硬盘中读取资源。在使用后用Resource.UnloadAsset()和Resources.UnloadUnusedAssets()尽快将其卸载掉。
    3Resources.UnloadUnusedAssets,释放已经没有引用的Asset.如果需要立即释放内存加上GC.Collect(),否则内存未必会立即被释放,有时候可能导致内存占用过多而引发异常。
C# Mono 托管 若干我们自己引入的DLL或者第三方DLL所需要的内存。
1 尽量不要使用foreach,而是使用for。foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾 mono的一个bug 新版本好像正常了
2 不要直接访问gameobject的tag属性。比如if (go.tag == “human”)最好换成if (go.CompareTag (“human”))。因为访问物体的tag属性会在堆上额外的分配空间
3 最好不用LINQ的命令,因为它们会分配临时的空间,同样也是GC收集的目标。而且我很讨厌LINQ的一点就是它有可能在某些情况下无法很好的进行AOT编译。 ios 不可用
4 控制StartCorountine()的次数:开启一个协程,至少分配37B的内存
5 常修改的string使用StringBuilder来代替String进行字符串拼接:StringBuilder.Append方法在拼
6 使用内建的数组,比如用Vector3.zero而不是new Vector(0, 0, 0);
7 对于方法的参数的优化:善于使用ref关键字。传递引用否则会用值传递,c# 泛型本身是引用
8 用内存池来重复利用对象
9 尽量使用栈对象 int float struct 减少gc压力
10尽量不要动态的instantiate和destroy object,使用object pool
11 不要动态的产生字符串,如Debug.Log("boo" + "hoo"),尽量预先创建好这些字符串资源
     gc调用
12游戏暂停时调用gc
13频繁的生成小对象,这些对象又只是暂时用。可以每隔一段时间调用一次gc 实现平滑过渡

CPU
目标
     Rigidbody数量:峰值 < 50/帧,对应Profiler中的Physics.Simulate。
     碰撞体数量:峰值 < 100/帧,对应Profiler中的Physics.Simulate。
方法
物理
1 不要使用 meshcollider 效率低.
2 每个rigidbody都消耗计算,所以越少越理想
3 对于投射物不要使用真实物理的碰撞和刚体,用自己的代码处理.
4 在edit->project setting->time中调大FixedTimestep(真实物理的帧率)来减少cpu损耗 并不是所有的游戏中物理计算都需要0.02秒执行一次。因此这个值,可以针对项目慢慢调试 
5 减少角色控制器移动命令的调用。移动角色控制器会同步发生,每次调用都会耗损极大的性能。我们的做法是缓存每帧的移动请求,并且仅运用一次。
函数
1 尽量不要再update函数中做复杂计算,如有需要,可以隔N帧计算一次
善于使用OnBecameVisible()和OnBecameVisible(),来控制物体的update()函数的执行以减少开销。
2 少用 GetComponent 它的开销很大,尤其在循环里
- GetComponent = 619ms
- Monobehaviour = 60ms
- CachedMB = 8ms
- Manual Cache = 3ms
3 GameObject.SetActive开销大 可以使用移到屏幕以外
4 尽量减少函数调用栈,用x = (x > 0 ? x : -x);代替x = Mathf.Abs(x)
5除法用乘法代替   x/2= x<<1  x/4 = x<<2 就是位移2的几次方
6如果可能,将GameObject上不必要的脚本disable掉。一个好的途径来开启或关闭GameObject是使用SetActiveRecursively(false).
如果你有一个大的场景在你的游戏中,并且敌方的位置在数千米意外,
这时你可以disable你的敌方AI脚本直到它们接近摄像机为止。 
7如不需要Start, Update, LateUpdate函数,请去掉他们

真机优化
1. 更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种,每家的GPU支持不同的压缩格式,但他们都兼容ETC格式, 
2 减少FPS,在ProjectSetting-> Quality中的VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
这两种情况都不符合游戏的FPS的话,我们需要手动调整FPS,首先关闭垂直同步这个功能,然后在代码的Awake方法里手动设置FPS(Application.targetFrameRate = 45;)
  降低FPS的好处:
 1)省电,减少手机发热的情况;
 2)能都稳定游戏FPS,减少出现卡顿的情况。 
3. 尽量少使用Update LateUpdate FixedUpdate,这样也可以提升性能和节省电量。多使用事件(不是SendMessage,使用自己写的,或者C#中的事件委托)。
4. 待机时,调整游戏的FPS为1,节省电量。


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值