Unity问答-性能调优

1.静态合批的原理是什么?会造成开销么?如果会,开销有哪些?

  • 静态批处理:游戏导出时,在player setting中勾选static batching,导出包的时候就进行批处理,导出来的包就会比较大。 在游戏场景中勾选场景的static选项,在加载场景时,会进行一次静态批处理合并,导出来的包不大,但加载时会使内存变大。
  • 场景中有4个物体,如果都勾选静态选项,在进行静态批处理的时候,引擎会判断这4个物体是否共用同一渲染材质。如果共用同一渲染材质,则会将这4个物体视为可批处理的对象,引擎会基于单个渲染对象的大小拷贝出3个,共变为4个人Mesh,这时4个Mesh会存在一个indexbuffer中,会让资源占用内存变大4倍,在渲染的时候,是将这个更大的mesh传递给GPU进行渲染操作的。
  • 如果CPU的运行速度较慢,则GPU会出现等待CPU的情况,此时哟咻主要受CPU的限制。 CPU在游戏中的主要作用是设置渲染状态和调用DC,如果每个物体的材质和贴图都不一样,CPU主要工作就是设置物体的渲染状态,调用DC也会更多,此时渲染状态的改变更消耗性能,游戏运行会变慢。所以,对于大量的不需要改变位置的物体,都会采用静态批处理的方式解决渲染状态的瓶颈。

2.动态合批的条件是什么?会造成开销么?如果会,开销有哪些?

  • Dynamic Batching 是在物件小于300的条件下(不论物件是否为静态或动态),在使用相同材质球下,unity就会自动帮你合并成一个Batch送往GPU来处理。
  • unity在运行的时可以将一些物体进行合并,从而用一个绘制调用来渲染他们。这一操作我们称之为“批处理”。一般来说,unity批处理的物体越多,你就会得到越好的渲染性能。
  • 动态批处理操作是自动完成的,并不需要你进行额外的操作。
  • 批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体。
  • 预设体的实例会自动地使用相同的网络模型和材质。

3.GPU Instancing 合批的条件是什么?

  • 使用不同材质的实例化物体将会导致批处理失败

4.Drawcall是什么?说说如何降低Drawcall?

  • 在unity中,每次CPU准备数据并通知GPU的过程称之为一个DrawCall。
  • 具体过程:设置颜色->绘图方式->顶点坐标->绘制->结束。所以在绘制过程中,如果能在一次DrawCall完成所有绘制就会大大提高运行效率,进而达到优化的目的。
  • why:为了CPU和GPU可以进行并行工作,就需要一个命令缓冲区,就是由CPU向其中添加命令,然后又GPU从中读取命令,这样就实现了通过CPU准备数据,通知GPU进行渲染。    每次调用DrawCall前,CPU需要向GPU发送很多内容,主要包括数据,渲染状态,命令等。
  • CPU具体的操作是:1.准备渲染对象,然后将渲染对象从硬盘加载到内存,然后从内存加载到显存,进而方便GPU高速处理。2.设置每个对象的渲染状态,也就是设置对象的材质,纹理,着色器等。3.输出渲染图元,然后向GPU发送DrawCall命令,并将渲染图元传递给GPU。  所以,DrawCall数量过多会导致大量CPU计算,进而导致CPU过载,影响游戏运行效率。
  • 优化:
  1. 关于图集,材质,层级的处理,减少DrawCall。只有相同材质的物体可以进行批处理,在程序中尽可能地复用材质和物体。如果两个材质仅仅纹理不同,可以通过纹理拼合操作将两张纹理合并一张大的纹理,就可以用单一材质来替代之前的两个材质了。
  2. 动态批处理,如果动态物体共用相同材质,unity会自动对这些物体进行批处理,并不需要进行额外操作。
  3. 对于复杂的静态场景,可以考虑自行设计遮挡剔除算法,减少可见的物体数量同时也可以减少DrawCall。
  4. 打包图集,从功能角度:ui可划分为公共部分,以及每个具体的界面,功能上,显示上密切相关的图品打包到一起。注意控制图集大小,不要太大,一个超级大的图集DrawCall消耗或许顶的上十几个小图集的消耗。
  5. 特效清理:特效播放结束的时候,没有将自身的active设为fasle,就会继续占用DrawCall,消耗设备的计算能力。所以,当一个特效播放完之后,能够被消耗或者设置为非激活状态,可以使用公共方法来完成特效播放完之后的清理工作。

5.SetPass Call 是什么?

  • 摄像机照射范围内,所有GameObject所包含的Material种类数量。
  • SetPass Call的数值低,DrawCall不一定低,但是SetPass Call的数值高,DrawCall一定高。
  • 优化DrawCall的时候,重点要将Bathes的数值降低。

6.Android/iOS平台的纹理格式分别设置成什么?有什么好处?

  • 最终决定图片占用内存的是它的像素格式和大小,与扩展名无关,png8,png32,jpg,pvr只要其像素格式都是argb8888,那么占用的内存是一样的。
  • 如果不是pvrtc4的格式,那么不要扩展成2的整次幂,图片越小,占用内存越小。
  • 单单去除透明通道不会减少图片所消耗的内存,png和jpg图片也无法减少图片体积,不推荐rgb888的格式,选择rgb565和rgb5551代替。
  • 如果为了减少图片体积可以选择:1.jpg--压缩比最高,质量最好,但不支持半透明 2. png8--同样图片会比jpg略大一些,使用imageAlpha进行转换,视觉上几乎看不出差别。这两种格式都极大减少图片体积,但无助于减少内存。

7.谈谈做游戏优化的一般思路是什么?

9.谈谈Unity 游戏引擎里面耗性能的主要有哪些地方?

10.Unity是如何绘制3D物体的?

11.Unity 减少GC开销,写代码要注意哪些方面?

  • 程序的运行会直接影响系统环境的变化,从而影响GC的触发,为了避免这些影响,基本原则就是尽可能减少垃圾和减少GC过程中的开销。
  1. 不要显式调用System.gc()。很多情况下它会触发主GC,从而增加主GC的频率,也增加了间歇性停顿的次数。
  2. 尽量减少临时对象的使用。临时对象在跳出函数调用后,会成为垃圾,少用临时变量就相当于减少了垃圾的产生,减少了主GC的机会。
  3. 对象不用时最好显式置为Null。一般而言,Null的对象都会被作为垃圾处理,所以将不用的对象显式地设为Null,有利于GC收集器判定为垃圾,从而提高了GC的效率。
  4. 尽量使用StringBuffer,而不用String来累加字符串。string是固定长的字符串,累加string对象时,不是在一个string对象中扩增,而是重新创建新的string对象,如str3 = str1 + str2 ,执行过程中会产生多个垃圾对象,因为座“+”操作时必须创建新的string对象,但这些过渡对象对系统来说是没有实际意义的,只会增加更多垃圾。避免这种情况可以改用stringbuffer来累加字符串,因为stringbuffer是可变长的,它在原有基础上进行扩增,不会产生中间对象。
  5. 能使用基本类型int,long,就不用Integer,Long对象。基本类型变量占用内存资源比相应对象占用少的多。
  6. 尽量少用静态对象变量。

猜你喜欢

转载自blog.csdn.net/wang_lvril/article/details/109194573