首页 > 技术文章 > 【总结】Unity游戏优化

sols 2018-02-20 17:44 原文

1、Profiler中一项"WaitForTargetFPS"费资源过高的原因
 
画面撕裂,显卡渲染输出的速度与显示器不同步, 如果显示器刷新的同时,显卡创造了新的帧,就会出现上半显示器显示前一帧,下半显示器刷新到下一帧画面的“撕裂”现象。常见于高帧数显卡与低帧数显示器上~
 
垂直同步(V-Sync),通过延时让显卡等显示器输出完毕后再“生产”下一帧画面,将游戏帧数锁定到和你的显示器刷新频率一样,从而达到画面的同步。
 
WaitForTargetFPS,是用于防止撕裂的。WaitForTargetFPS消耗越高,说明被压缩的帧数越多,Setting里关掉垂直同步就可以了
 
FreeSync技术则是让显示器的刷新率不再固定为60Hz,成为一个动态变量,当显卡完整渲染完一张画面后,显示器就可以输出了。 最大化发挥显卡性能,不会因垂直同步而掉帧
 
2、代码细节优化
  • 协程比Update节能,尽量不要在update函数中做复杂计算,有需要可以隔N帧计算一次
  • 不用的事件函数如Update应该删除
  • 简化计算,如用乘法代替除法,少用复杂的数学函数,用合适的精度
  • 减少使用临时变量,尽量优化循环的时间空间复杂度
  • 减少动态的生成字符串,用StringBuilder
  • 减少使用Find,GetComponent等耗时API,可以在start中预先存起来
  • 减少函数调用栈,用x = (x > 0 ? x : -x);代替x = Mathf.Abs(x)
  • 尽量不要在方法中动态new array,推荐用类变量或者传入参数
  • OnGUI少用,最好只在一个脚本中使用。用UGUI
 
3、用Profiler优化
  • ProcessRemoteInput 是引擎在Editor下调用的东西……
  • Log中可以找到所有打包的资源(AssetHunter)
4、场景优化
  • 无用的组件比如Animation最好移除
  • 少用耗性能的碰撞体,比如mesh,wheel,sphere...尤其是移动端
  • 不要在场景预先放好太多东西,而是用动态生成,逐渐加载
  • 阴影=阴暗+影子,建议使用实时影子时把阴暗效果烘焙出来,不要使用灯光来调节光线阴暗。
  • 在效果相似时选择最节能的。比如硬阴影,低分辨率贴图,static光照烘焙,少用法线贴图,优化粒子特效或用UV动画
  • 大场景中使用线性雾,使远距离对象或阴影不易察觉,因此可通过减小相机和阴影距离来提高性能
  • 使用遮挡剔除,LOD
  • 用skybox做远景
 
5、资源加载优化
  • 使用对象池
  • 合并使用同贴图的材质球,合并使用相同材质球的Mesh
  • 动画文件我们是单独分离出来的,以供多角色共用
  • 减少模型面数和总数。但是场景不用合并成一个mesh,这样会使得同屏的面数增加
  • 将透明通道的对象置于TransparentFX图层。Tag,Hieratchy,Layer养成良好的条理化习惯
  • Mesh的压缩仅仅是减少打包文件的大小,并不会减少运行时的内存消耗。而减少动画关键帧,则会让两者都有所减少,一般情况下我们都应该开启。 
  • 减少手机上使用的 .NET 库的大小,通常用 .NET 2.0 Subset ,另外Unity会自动随着API的使用提高安卓版本
 
Textures资源设置
  1. 对于Texture等资源来说, Unity会把资源再编码成它自己的内部格式,所以源文件格式并不重要。而内部格式文件占空间越小,存储空间优化就越好
  2. 可以用压缩来优化存储空间,但会损失一些时间,而且内存消耗不变
 
6、Shader优化
  1. 少使用的函数:pow,sin,cos等
  2. 用合适大小的数据类型
  3. 对于不支持的设备不使用逐像素、实时阴影、屏幕特效等画面效果。Shader要做到平台适用且高效
 
7、内存管理,GC回收
  1. Mono堆内存回收用 System.GC.Collect(); 可避免系统在不合适的时间进行自动GC
  2. Unity内存回收用 Resources.UnloadUnusedAssets(); 其内部本身也会调用 GC.Collect()
  3. AssetBundle.Unload 释放AssetBundle文件内存镜像
  4. Reources.UnloadAsset(Object) 释放硬盘加载的所有Asset资源,慎用
 
 

推荐阅读