浅谈Unity3D游戏如何优化~

作者:BoBoWang1991

作为一个入行不足三年的攻城狮来讲,讲引擎中的优化,经验确实不足,unity3D引擎作为一款侧重移动端游戏开发引擎来讲,优化游戏是确实有必要的,毕竟他要适配所有机型的前提下又要保证游戏画面的清晰度,特效的绚丽多彩,所以国内大部分游戏公司都要喜欢招收既会码代码又会做优化的复合人才。

废话不多说,直接上方案。

性能优化

1. CPU优化

浅谈Unity3D游戏如何优化

1.DrawCalls

新版Unity也可以叫DrawCall,定义:Unity每次在准备数据并通知GPU渲染的过程称为一次DrawCall,显示在工程中就是Batches的大小,Batches越大,画面越是卡顿,不流畅。

浅谈Unity3D游戏如何优化

通常来说,如果是在pc端发布的游戏,DrawCall应该控制在2000以内,如果是要发布到移动端,那么DrawCall最大不能超过300,越低越好,当然在保证画面质量的前提下。那么如何降低DrawCall呢,我在这里说两种最常用的方法,第一种:静态批处理Batching Static,批处理相同材静态独享或者相同纹理的静态对象,直接上图。

浅谈Unity3D游戏如何优化

2. 动态批处理

即是批处理非静态对象,但是要求苛刻,稍作修改就会批处理不成功,我建议大家使用静态批处理

浅谈Unity3D游戏如何优化

物理组件

1. 设置一个合适的FixedTimestep.

浅谈Unity3D游戏如何优化

Editor-ProjectSetting-Time,打开可以根据需求动态设置。

2. 不要使用MeshCollder,从优化角度来看,尽量减少物理组件的使用。

MeshCollider顾名思义,即是网格碰撞器,如果非要使用,建议大家使用Meshbaker网格合并,合并碰撞器,这一点我设计的有些少,发一个链接,大家可以参考一下。
http://blog.csdn.net/akof1314/article/details/41347079

3.GC(Garbage Collection垃圾回收)

处理器-调度->GC回收垃圾。

在我们做需要大量生成和销毁游戏对象的游戏时,如FPS类游戏,如果频繁实例化Instantiate和Destroy,则会大量调度GC,从而严重消耗CPU性能,在这里,我就可以使用对象池模式来减少GC的调度,何为对象池呢,对象池就是存放需要被反复调用资源的一个空间,当一个对象会大量生成的时候,如果每次都销毁创建,会非常浪费时间,通过对象池把暂时不用的对象放到一个池子中(也就是一个集合中),当下次要重新生成这个对象的时候,先去池子中查找一下是否有可用的对象,如果有就直接拿出来使用,如果没有,就重新创建,利用空间换时间来达到游戏的告诉运行,减少GC的调度。

大家可以参考我对象池的链接,学习一下。 链接:http://blog.csdn.net/bobowang1991/article/details/68961877

另外降低GC的方案如下,
1. 减少New产生对象的次数,
2. 使用公共的对象(静态成员),
3. 将String换成StringBundle.都可以减少GC的调度,
4. 尽量不用foreach,而是用for,foreach会涉及到迭代器的使用,每一次循环所产生的迭代器会带来24bytes的垃圾,循环10次,就是240bytes。
5. 不要直接访问gameobject的tag属性,访问物体的tag属性会在堆上额外的分配空间。
6. LinQ->连接数据库。

代码质量

1. 不要频繁的使用GetComponent,尤其在循环中。
2. 善于使用OnBecameVisible()he1OnBecameInVisible().
3. 使用内建的数组,如Vecter.Zero而不是new Vector3(0,0,0).
4. 善于使用ref关键字
5. 将经常需要使用的属性查询缓存起来。
6. 不要频繁使用Instantiate和Destroy,使用对象池。
7. 习惯性的将暂时不用的GameObject设置为非激活,即使把

浅谈Unity3D游戏如何优化

GPU的优化

两种方案:
1. 减少绘制的数目,
2. 优化显存带宽。

如何减少绘制的数目
1. 保持材质的数目尽可能少,这使得unity更容易进行批处理。
2. 使用纹理图像,来代替一些列单独的小贴图。
3. 如使用了纹理图像和共享材质,使用Render.SharedMaterial代替Render.material。
4. 使用光照纹理,Lightmap,而非实时灯光,这一点尤为重要,但是操作起来不难,我在这里着重讲解。

首先,如果是一个加了大量的灯光和粒子特效,即使是一个小小的塔防游戏,DrawCall也会达到5000以上甚至更高,这是为什么呢,是因为灯光和粒子特效需要GPU实时渲染,灯光和粒子特效的数量越多,DrawCall也就越高。但是我们场景中的灯光是不需要实时渲染的,如果你场景中的灯光很多时,就只需要下面的操作就可以大大降低DrawCall,优化GPU。

首先打开unity中的Windows面板-Light-选择Lights,然后把Baking选择为Baked类型,右下角Auto勾去掉,选择Build等待烘焙完毕即可,如下图所示

浅谈Unity3D游戏如何优化

大家需要实际操作一下,当然需要实时渲染的灯光不要要烘焙,问题不大。

5. 使用LOD,LOD即是远的看不清的物体的细节忽略,当靠近他时才让渲染他的细节,说白了就是物体在远处时,虽然我们的肉眼看不清,但是相机还是在渲染他的所有细节,这是不需要的,此时我们可以使用LOD,把精细的模型换成粗模,一次来减少GPU的渲染,具体操作如下图所示。

浅谈Unity3D游戏如何优化

浅谈Unity3D游戏如何优化

6. 遮挡剔除

(1) 当场景中包含大量模型时,造成渲染效率的降低(即帧速率FPS的降低),采用遮挡剔除技术,可以使得那些被阻挡的物体不被渲染提高渲染效率

(2) 原理:在场景空间中创建一个遮挡区域,该遮挡区域是有单元格(Cell)组成;每个单元格是构成整个场景遮挡区域的一部分,这些单元格会把整个场景拆分成多个部分,当摄像机能够看到该单元格时,表示该单元格的物体会被渲染出来,其他的不去渲染

(3) 遮挡剔除步骤:
① 场景
② 除了主角,摄像机,直线光,地面。把层级视图中的所有游戏对象标记为“遮挡静态”(Occluder Static/Occludee Static)
③ 执行菜单命令“Windows”—>“Occlusion Culling”,弹出“遮挡剔除”面板,单击下方的“Back”按钮,开始烘焙
④ 单击“遮挡剔除”(Occlusion)窗口的“Visualizatior”,运行程序

(4) 若场景中存在大量的小“物件”,使用“层消隐距离”来优化场景
① 原理:较远距离将小物件剔除,减少绘图调用的数量
② 方法:将小物件放入一个单独的层(Separate Layer)中,并使用Camera.main.layerCullDistances函数设置层的消隐距离
③ 例如:

void Start(){ 
Float[] distances=new float[32]; 
//这里定义的数组下标“8”表明第8层 
distances[8]=10; 
Camera.main.layerCullDistances=distances; 
} 

当摄像机距离这些小物件超过10m的时候,就不可见了

7. 使用mobile版的shader。

具体操作入下,新建一个mateiral,inspector-Shader-Mobile-选择需要的类型,适合移动端的发布,pc端也可以使用,包括天空盒也可以使用。

浅谈Unity3D游戏如何优化

优化显存带宽

1. OpenGL ES 2.0使用ETC1格式压缩等等,在打包设置哪里都有这些选项,点击选择即可。

2. MipMap技术

MipMap是把图片处理成预先计算好的比较小的图集,在在屏幕尺寸变小时调用处理好的小图,以此来节约GPU渲染,但是缺点是会增加33%的图集内存,因为原图还要保存。

浅谈Unity3D游戏如何优化

浅谈Unity3D游戏如何优化

Unity3D内部的优化

1. Resources 资源不用的要删除,纹理,网格,音频,组件等等。

2. 在CPU压力不是很大的时候,重置GameObject,组件等占用的内存。

3. 在打AssetBundle的时候,可以考虑bundle的压缩等等。

以上为本人近两年工作中所用到的所有优化技术方案,希望对大家有所帮助,谢谢。

本文转自 CSDN,为博主 BoBoWang1991 的原创文章,
遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/BoBoWang1991/article/details/68959365

最新文章