• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

游戏开发

unity项目优化手段

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/youxikaifa/2019/0402/436.html

unity项目优化手段


最简单的优化倡议:
 
1.PC平台的话坚持场景中显现的顶点数少于200K~3M,挪动设备的话少于10W,一切取决于你的目的GPU与CPU。
 
2.假如你用U3D自带的SHADER,在表现不差的状况下选择Mobile或Unlit目录下的。它们更高效。
 
3.尽可能共用材质。
 
4.将不需求挪动的物体设为Static,让引擎能够停止其批处置。
 
5.尽可能不用灯光。
 
6.动态灯光愈加不要了。
 
7.尝试用紧缩贴图格式,或用16位替代32位。
 
8.假如不需求别用雾效(fog)
 
9.尝试用OcclusionCulling,在房间过道多遮挡物体多的场景十分有用。若不当反而会增加担负。
 
10.用手机App外包天空盒去“褪去”远处的物体。
 
11.shader中用贴图混合的方式去替代多重通道计算。
 
12.shader中留意float/half/fixed的运用。
 
13.shader中不要用复杂的计算pow,sin,cos,tan,log等。
 
14.shader中越少Fragment越好。
 
15.留意能否有多余的动画脚本,模型自动导入到U3D会有动画脚本,大量的话会严重影响耗费CPU计算。
 
16.留意碰撞体的碰撞层,不用要的碰撞检测请舍去。
 
1.为什么需求针对CPU(中央处置器)与GPU(图形处置器)优化?
 
CPU和GPU都有各自的计算和传输瓶颈,不同的CPU或GPU他们的性能都不一样,所以你的游戏需求为你目的用户的CPU与GPU才能停止针对开发。
 
2.CPU与GPU的限制
 
GPU普通具有填充率(Fillrate)和内存带宽(Memory Bandwidth)的限制,假如你的游戏在低质量表现的状况下会快很多,那么,你很可能需求限制你在GPU的填充率。
 
CPU普通被所需求渲染物体的个数限制,CPU给GPU发送渲染物体命令叫做DrawCalls。普通来说DrawCalls数量是需求控制的,在能表现效果的前提下越少越好。通常来说,电脑平台上DrawCalls几千个之内,挪动平台上DrawCalls几百个之内。这样就差不多了。当然以上并不是绝对的,仅作一个参考。
 
常常渲染(Rendering)并不是一个问题,无论是在GPU和CPU上。很可能是你的脚本代码效率的问题,用Profiler查看下。
 
关于Profiler引见:http://docs.unity3d.com/Documentation/Manual/Profiler.html
 
需求留意的是:
 
在GPU中显现的RenderTexture.SetActive()占用率很高,是由于你同时翻开了编辑窗口的缘由,而不是U3D的BUG。
 
3.关于顶点数量和顶点计算
 
CPU和GPU对顶点的计算处置都很多。GPU中渲染的顶点数取决于GPU性能和SHADER的复杂水平,普通来说,每帧之内,在PC上几百万顶点内,在挪动平台上不超越10万顶点。
 
CPU中的计算主要是在蒙皮骨骼计算,布料模仿,顶点动画,粒子模仿等。GPU则在各种顶点变换、光照、贴图混合等。
 
【个人以为,详细还是看各位的项目需求,假定你项目的是3d游戏。你游戏需求兼容低配置的硬件、流利运转、控制硬件发热的话,还要到达一定效果(LIGHTMAP+雾效),那么顶点数必定不能高。此时同屏2W顶点我以为是个比拟适宜的数目,DRAWCALL最好低于70。另,控制发热请控制最高上限的帧率,流利的话,帧率其实不需求太高的。】
 
4.针对CPU的优化——减少DRAW CALL 的数量
 
为了渲染物体到显现器上,CPU需求做一些工作,如辨别哪个东西需求渲染、辨别开物体能否受光照影响、运用哪个SHADER并且为SHADER传参、发送绘图命令通知显现驱动,然后发送命令通知显卡删除等这些。
 
假定你有一个上千三角面的模型却用上千个三角型模型来替代,在GPU上破费是差不多的,但是在CPU上则是极端不一样,耗费会大很多很多。为了让CPU更少的工作,需求减少可见物的数目:
 
a.兼并相近的模型,手动在模型编辑器中兼并或者运用UNITY的Draw call批处置到达相同效果(Draw call batching)。详细办法和留意事项查看以下链接:
 
Draw call batching : http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html
 
b.在项目中运用更少的材质(material),将几个分开的贴图合成一个较大的图集等方式处置。
 
假如你需求经过脚原本控制单个材质属性,需求留意改动Renderer.material将会形成一份材质的拷贝。因而,App开发培训你应该运用Renderer.sharedMaterial来保证材质的共享状态。
 
有一个兼并模型材质不错的插件叫Mesh Baker,大家能够思索试下。
 
c.尽量少用一些渲染步骤,例如reflections,shadows,per-pixel light 等。
 
d.Draw call batching的兼并物体,会使每个物体(兼并后的物体)至少有几百个三角面。
 
假定兼并的两个物体(手动兼并)但不共享材质,不会有性能表现上的提升。多材质的物体相当于两个物体不用一个贴图。所以,为了提升CPU的性能,你应该确保这些物体运用同样的贴图。
 
另外,用灯光将会取消(break)引擎的DRAW CALL BATCH,至于为什么,查看以下:
 
Forward Rendering Path Details:
 
http://docs.unity3d.com/Documentation/Components/RenderTech-ForwardRendering.html
 
e.运用相关剔除数量直接减少Draw Call数量,下文有相关提及。
 
5.优化几何模型
 
最根本的两个优化原则:
 
a.不要有不用要的三角面。
 
b.UV贴图中的接缝和硬边越少越好。
 
需求留意的是,图形硬件需求处置顶点数并跟硬件报告说的并不一样。不是硬件说能渲染几个点就是几个点。模型处置应用通展现的是几何顶点数量。例如,一个由一些不同顶点构成的模型。在显卡中,一些汇合顶点将会被别离(split)成两个或者更多逻辑顶点用作渲染。假如有法线、UV坐标、顶点色的话,这个顶点必需会被别离。所以在游戏中处置的实践数量显然要多很多。
 
6.关于光照
 
若不用光肯定是最快的。挪动端优化能够采用用光照贴图(Lightmapping)去烘培一个静态的贴图,以替代每次的光照计算,在U3D中只需求十分短的时间则能生成。这个办法能大大进步效率,而且有着更好的表现效果(平滑过渡处置,还有附加阴影等)。
 
在挪动设备上和低端电脑上尽量不要在场景中用真光,用光照贴图。这个办法大大俭省了CPU和GPU的计算,CPU得到了更少的DRAWCALL,GPU则需求更少顶点处置和像素栅格化。
 
Lightmapping : http://docs.unity3d.com/Documentation/Manual/Lightmapping.html
 
7.对GPU的优化——图片紧缩和多重纹理格式
 
Compressed Textures(图片紧缩):
 
http://docs.unity3d.com/Documentation/Components/class-Texture2D.html
 
图片紧缩将降低你的图片大小(更快地加载更小的内存跨度(footprint)),而且大大进步渲染表现。紧缩贴图比起未紧缩的32位RGBA贴图占用内存带宽少得多。
 
之前常州网站开发培训U3D会议还听说过一个优化,贴图尽量都用一个大小的格式(512 * 512 , 1024 * 1024),这样在内存之中能得到更好的排序,而不会有内存之间空隙。这个能否真假没得到过测试。
 
MIPMAps(多重纹理格式):
 
http://docs.unity3d.com/Documentation/Components/class-Texture2D.html
 
跟网页上的略缩图原理一样,在3D游戏中我们为游戏的贴图生成多重纹理贴图,远处显现较小的物体用小的贴图,显现比拟大的物体用精密的贴图。这样能愈加有效的减少传输给GPU中的数据。
 
8.LOD 、 Per-Layer Cull Distances 、 Occlusion Culling
 
LOD (Level Of Detail) 是很常用的3D游戏技术了,其功用了解起来则是相当于多重纹理贴图。在以在屏幕中显现模型大小的比例来判别运用高或低层次的模型来减少对GPU的传输数据,和减少GPU所需求的顶点计算。
 
摄像机分层间隔剔除(Per-Layer Cull Distances):为小物体标识层次,然后依据其间隔主摄像机的间隔判别能否需求显现。
 
遮挡剔除(Occlusion Culling)其实就是当某个物体在摄像机前被另外一个物体完整挡住的状况,挡住就不发送给GPU渲染,从而直接降低DRAW CALL。不过有些时分在CPU中计算其能否被挡住则会很耗计算,反而得失相当。
 
以下是这几个优化技术的相关运用和引见:
 
Level Of Detail :
 
http://docs.unity3d.com/Documentation/Manual/LevelOfDetail.html
 
Per-Layer Cull Distances :
 
http://docs.unity3d.com/Documentation/ScriptReference/Camera-layerCullDistances.html
 
Occlusion Culling :
 
http://docs.unity3d.com/Documentation/Manual/OcclusionCulling.html
 
9.关于Realtime Shadows(实时阴影)
 
实时阴影技术十分棒,但耗费大量计算。为GPU和CPU都带来了昂贵的担负,细节的话参考下面:
 
http://docs.unity3d.com/Documentation/Manual/Shadows.html
 
10.对GPU优化:采用高效的shader
 
a.需求留意的是有些(built-in)Shader是有mobile版本的,这些大大进步了顶点处置的性能。当然也会有一些限制。
 
b.本人写的shader请留意复杂操作符计算,相似pow,exp,log,cos,sin,tan等都是很耗时的计算,最多只用一次在每个像素点的计算。不引荐你本人写normalize,dot,inversesqart操作符,内置的肯定比你写的好。
 
c.需求警醒的是alpha test,这个十分耗时。
 
d.浮点类型运算:精度越低的浮点计算越快。
 
在CG/HLSL中–
 
float :32位浮点格式,合适顶点变换运算,但比拟慢。
 
half:16位浮点格式,合适贴图和UV坐标计算,是highp类型计算的两倍。
 
fixed: 10位浮点格式,合适颜色,光照,和其他。是highp格式计算的四倍。
 
写Shader优化的小提示:
 
http://docs.unity3d.com/Documentation/Components/SL-ShaderPerformance.html
 
11.另外的相关优化:
 
a.对Draw Call Batching的优化
 
http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html
 
b.对Rendering Statistics Window的阐明和提示:
 
http://docs.unity3d.com/Documentation/Manual/RenderingStatistics.html
 
c.角色模型的优化倡议
 
用单个蒙皮渲染、尽量少用材质、少用骨骼节点、挪动设备上角色多边形坚持在300~1500内(当然还要看详细的需求)、PC平台上1500~4000内(当然还要看详细的需求)。
 
http://docs.unity3d.com/Documentation/Manual/ModelingOptimizedCharacters.html
 
优化:
 
1. 更新不透明贴图的紧缩格式为ETC 4bit,由于android市场的手机中的GPU有多种,
 
每家的GPU支持不同的紧缩格式,但他们都兼容ETC格式,
 
2. 关于透明贴图,我们只能选择RGBA 16bit 或者RGBA 32bit。
 
3. 减少FPS,在ProjectSetting-> Quality中的
 
VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
 
常州企业培训这两种状况都不契合游戏的FPS的话,我们需求手动调整FPS,首先关闭垂直同步这个功用,然后在代码的Awake办法里手动设置FPS(Application.targetFrameRate = 45;)
 
降低FPS的益处:
 
1)省电,减少手机发热的状况;
 
2)能都稳定游戏FPS,减少呈现卡顿的状况。
 
4. 当我们设置了FPS后,再调整下Fixed timestep这个参数,
 
这个参数在ProjectSetting->Time中,目的是减少物理计算的次数,来进步游戏性能。
 
5. 尽量少运用Update LateUpdate FixedUpdate,这样也能够提升性能和俭省电量。
 
多运用事情(不是SendMessage,运用本人写的,或者C#中的事情拜托)。
 
6. 待机时,调整游戏的FPS为1,俭省电量。
 
7. 图集大小最好不要高于1024,否则游戏装置之后、低端机直接解体、缘由是手机系统版本低于2.2、超越1000的图集无法读取、招致。
 
2.2 以上没有遇见这个状况。
 
留意手机的RAM 与 ROM、小于 512M的手机、直接放弃机型适配。
 
VSCount 垂直同步
 
unity3d中新建一个场景空的时分,帧速率(FPS总是很低),大约在60~70之间。
 
不断不太明白是怎样回事,如今根本上明白了。我在这里解释一下缘由,如有错误,欢送指正。
 
在Unity3D中当运转场景翻开Profiler的时分,我们会看到VSync 这一项占了很大的比重。
 
这个是什么呢,这个就是垂直同步,稍后再做解释。
 
我们能够关闭VSync来进步帧速率,选择edit->project settings->Quality。
 
在右侧面板中能够找到VSync Count,把它选成Don’t Sync。
 
这就关闭了VSync(垂直同步),如今在运转场景看看,帧速率是不是进步很多。
 
如今来说说什么是垂直同步,要晓得什么是垂直同步,必需要先明白显现器的工作原理,
 
显现器上的一切图像都是一线一线的扫描上去的,无论是隔行扫描还是逐行扫描,
 
显现器都有两种同步参数——程度同步和垂直同步。
 
什么叫程度同步?什么叫垂直同步?
 
垂直和程度是CRT中两个根本的同步信号,程度同步信号决议了CRT画出一条横越屏幕线的时间,
 
垂直同步信号决议了CRT从屏幕顶部画到底部,再返回原始位置的时间,
 
而恰恰是垂直同步代表着CRT显现器的刷新率程度。
 
为什么关闭垂直同步信号会影响游戏中的FPS数值?
 
假如我们选择等候垂直同步信号(也就是我们平常所说的垂直同步翻开),
 
那么在游戏中或许强劲的显卡疾速的绘制完一屏的图像,但是没有垂直同步信号的抵达,
 
显卡无法绘制下一屏,只要等85单位的信号抵达,才能够绘制。
 
这样FPS自然要遭到操作系统刷新率运转值的限制。
 
而假如我们选择不等候垂直同步信号(也就是我们平常所说的关闭垂直同步),那么游戏中作完一屏画面,
 
显卡和显现器无需等候垂直同步信号就能够开端下一屏图像的绘制,自然能够完整发挥显卡的实力。
 
但是不要遗忘,正是由于垂直同步的存在,才干使得游戏进程和显现器刷新率同步,使得画面愈加平滑和稳定。
 
取消了垂直同步信号,固然能够换来更快的速度,但是在图像的连续性上势必打折扣。
 
这也正是很多朋友埋怨关闭垂直后发现画面不连续的理论缘由。
 
兼并材质球unity 3d中每倒入一次模型就多一个材质球,可我的这些模型都是共用一张贴图的就想共用一个材质球,所以每次都要删除再附上,很费事。怎样才干兼并这些材质球?
 
采用TexturePacking吧
 
1、遍历gameobject,取出material,并依据shader来将material分类
 
2、调用Unity自带的PackTextures函数来兼并每个shader分类中的material所对应的textures(PackTextures函数有缺陷,不过能够凑合用)
 
3、依据兼并的大的texture来更新原有模型的texture、material曾经uv坐标值。
 
需求留意的是:需求兼并的纹理应该是物体在场景中间隔相近的,假如物体在场景中的间隔较远,
 
则不倡议兼并纹理,由于这样做很有可能非但起不到优化的作用,反而降低了运转效率。
 
mesh兼并
 
分为2种方式兼并:
1.自带的兼并必需勾选静态。
一切被勾选了“Static”的GameObject,其中的Mesh Filter中的mesh都会被兼并到 "Combined Mesha (root: scene)" 中
 
2.也能够用脚原本兼并mesh 。
using UnityEngine;
using System.Collections;
public class MyClass: MonoBehaviour
    void Start()
    {
        MeshFilter[] meshFilters = GetComponentsInChildren ();
        CombineInstance[]combine = new CombineInstance[meshFilters.Length];
        for (int i= 0; i < meshFilters.Length; i++) {
            combine[i].mesh = meshFilters [i].sharedMesh;
            combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
            meshFilters[i].gameObject.active = false;
        }
            transform.GetComponent().mesh = new Mesh();
            transform.GetComponent().mesh.CombineMeshes (combine);
            transform.gameObject.active= true;
    }
1.先在 Unity 中树立 空物件 ( Empty )
2.再创立2个 Cube 方块,并放入 空物件底下 (能够改成你本人的模型)
3.把 MyClass 代码丢进 空物件上 。
4.(可选) 树立一个 Material 材质,并且丢进 空物件上
5.执行
 
常州软件技术培训角色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。
 
挪动平台相关于PC机,具有体积小,计算弱,带宽少的特性。
因而做手机游戏的开发,优化的方向,与力度比照PC游戏都有所区别。
 
必需要做到优化流程,合理应用资源。
目前在手机上面,还不可以像PC游戏那样追求高质量渲染效果,为了让手机不那么容易发烫,还要控制cpu,gpu,不能让他们全速运算。
 
材质方面:
纹理方面,倡议运用紧缩纹理,
Android上面运用ETC1,苹果上面运用PVRTC。
 
UV坐标控制在0到1之间,人物模型面数控制在1500内,骨骼控制在30个以内。
场景中运用一个主光(不能再多了)。
 
尽量减少alphaTest和alphaBlend材质的运用。在手机上,这是很杀效率的。
 
骨骼动画方面:
在动画方面能够思索不运用插值,固定的帧率的动画。
假如要做插值,思索运用四元数(表示旋转)和向量(表示位移)来做插值。
四元数做插值速度比矩阵来的快,Slerp提供了平滑插值。
 
优化的常规技巧
 
分析你的游戏。
不要破费时间来优化那些晦涩的代码或者缩减图形文件的大小,除非这是你游戏的瓶颈。
第一次分析你的游戏将会使你发现你游戏的瓶颈。Apple’s Shark是一个很好的用来分析基于OpenGL的程序的工具。
 
再次分析你的游戏。
优化之后不要遗忘再分析一次你的游戏,这样能够检查你所做的优化能否到达了预期的效果。
当然,这样做也可能会使你发现更多的瓶颈。
流程第一、性能第二。破费时间来使你游戏的创立尽可能地流利。
尽可能快地修正游戏中的错误将会使你后期更容易优化你的游戏。
 
在Scene View中测试场景。
常州平台运营这样做将会使你分明理解这个场景中的物体或者附加在物体上的脚本能否降低了游戏性能。
假如Scene View反响愚钝,那么有可能是图形方面的缘由,假如Scene View反响不愚钝,那么瓶颈可能出在脚本或者物理系统上。
禁用指定游戏物体。
在play形式下,尝试禁用并启用游戏物体来排查出游戏慢的缘由。
 
网格
 
假如可能的话,把相邻的物体(网格)兼并为一个只要一个材质的物体(网格)。比方,你的游戏中包含一个桌子,上面有一堆东西,你完整能够在3D程序中将它们兼并在一同(这可能也需求你将这些物体的纹理兼并为一个大的纹理集)。减少需求渲染的物体的数量能够极大地进步游戏性能。
 
不要有不用要的网格。
假如你的游戏场景中有一个人物,那么他应该是一个网格。假如你有一个船,那么它也应该只是一个网格。
每一个网格只用一种材质。
运用极少的面数的网格(比方500个多边形以下)。
最好把你人物的三角面数量控制在1500-2000个之间。
这个数量能够说是游戏质量和性能之间一个平衡值。假如你的模型有四边形,那么在导入模型的时分,引擎将会把每个四边形变为两个三角形。
 
光照
 
像素光。
像素光能够让你的游戏看起来效果很牛逼,但是不要运用过多的像素光。
在你的游戏中能够运用质量管理器来调理像素光的数量来获得一个性能和质量的平衡点。
 
性能占用次第:聚光灯>点光源>平行光。
一个好的点亮场景的办法就是先得到你想要的效果,然后看看哪些光更重要;
在坚持光效的前提下看看哪些光能够去掉。
 
点光源和聚光灯只影响它们范围内的网格。
假如一个网格处于点光源或者聚光灯的映照范围之外,并且光源的attenuate开关是翻开的,那么这个网格将不会被光源所影响,这样就能够俭省性能开支。
这样做理论上来讲能够运用很多小的点光源而且仍然能有一个好的性能,由于这些光源只影响一小局部物体。
一个网格在有8个以上光源影响的时分,只响应前8个最亮的光源。
 
贴图
 
在外观不变的前提下,贴图大小越小越好。
假如你的显卡的显存不够大的话,你游戏中的贴图将会被转存到系统内存中,在显卡调用它们的时分再传到显卡中。
关于比拟新的电脑来说,内存和显卡之间有足够的带宽来到达一个很好的性能;
假如你很无耻地用了巨多的大图片的话,在低显存的电脑上运转你的游戏的时分,你的游戏必然会挂掉。
倒是没有必要在图形编辑软件中调整贴图的大小。你能够在unity导入贴图的时分停止调整。
 
不要运用低质量的图片。
在小播放界面的游戏中运用低质量的jpeg图片或者低颜色的png图片亦或是gif图片没什么问题。
在发布游戏的时分,引擎会自动紧缩这些图片,多重紧缩和解压将会降低图片的质量,所以最好坚持贴图文件的分辨率为原始分辨率。
这样就会减少多重紧缩和解压所招致的图片失真现象。
 
Shaders
 
多重效果的shader就比看起来款式很单一的shader要更消耗资源。
同样在一个具有贴图和光反射的物体上,运用VertexLit Diffuse shader无疑是最省资源的。
 
————————-分割线————————-
 
在美术制造场景的过程中,会运用到大量的粒子系统。
比方场景中的火把。在我们的一个公开城场景中,美术们放置了大量的火把。整个场景中的各个中央,有100来个火把。
 
unity中,在摄像机范围外的粒子系统固然不会被绘制。
但是update是不断持续的。这也就意味着,这100多个火把,不管能否可见都在更新。
 
这个设计应该是很不合理的,在我看过的其他引擎中,都会有一个开关,来控制不可见的粒子系统能否需求update。
有的粒子系统在不可见的时分需求更新,比方爆炸。有的不需求更新,比方火堆火把。
 
为了防止不用要的update开支,特别是最后游戏是要发布到页游平台(web player只能运用一个cpu的核)。
于是写了一个脚本,控制不可见的粒子系统就不更新。
 
该脚本主要是用到了2个MonoBehaviour的函数。
OnBecameInvisible() 当变为不可见   和   OnBecameVisible() 当变成可见。
 
要这2个函数起作用的前提是,该GameObject绑定了MeshRender组件。
所以,我们要在粒子系统的GameObject放置在一个GameObject  下,且给该GameObject绑定一个MeshRender 与 MeshFilter。
MeshFilter中的mesh能够随意找个cube。
 
在Start() 的时分,把最GameObject的scale设置为很小,以保证该cube不被看见。
其实遍历一切的child,把active设置为false。
 
在OnBecameVisible 中 遍历一切child,把active设置为true。
在OnBecameInvisible中 遍历一切child,把active设置为false。
 
Unity 性能优化 Draw Call
 
Unity(或者说根本一切图形引擎)生成一帧画面的处置过程大致能够这样简化描绘:引擎首先经过简单的可见性测试,肯定摄像机能够看到的物体,然后把这些物体的顶点(包括本位置置、法线、UV等),索引(顶点如何组成三角形),变换(就是物体的位置、旋转、缩放、以及摄像机位置等),相关光源,纹理,渲染方式(由材质/Shader决议)等数据准备好,然后通知图形API——或者就简单地看作是通知GPU——开端绘制,GPU基于这些数据,经过一系列运算,在屏幕上画出成千上万的三角形,最终构成一幅图像。
 
在Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。这一过程是逐一物体停止的,关于每个物体,不只GPU的渲染,引擎重新设置材质/Shader也是一项十分耗时的操作。因而每帧的Draw Call次数是一项十分重要的性能指标,关于iOS来说应尽量控制在20次以内,这个值能够在编辑器的Statistic窗口看到。
 
Unity内置了Draw Call Batching技术,从名字就能够看出,它的主要目的就是在一次Draw Call中批量处置多个物体。只需物体的变换和材质相同,GPU就能够按完整相同的方式停止处置,即能够把它们放在一个Draw Call中。Draw Call Batching技术的中心就是在可见性测试之后,检查一切要绘制的物体的材质,把相同材质的分为一组(一个Batch),然后把它们组合成一个物体(统一变换),这样就能够在一个Draw Call中处置多个物体了(实践上是组合后的一个物体)。
 
但Draw Call Batching存在一个缺陷,就是它需求把一个Batch中的一切物体组合到一同,相当于创立了一个与这些物体加起来一样大的物体,与此同时就需求分配相应大小的内存。这不只会耗费更多内存,还需求耗费CPU时间。特别是关于挪动的物体,每一帧都得重新停止组合,这就需求停止一些权衡,否则得失相当。但关于静止不动的物体来说,只需求停止一次组合,之后就能够不断运用,效率要高得多。
 
Unity提供了Dynamic Batching和Static Batching两种方式。Dynamic Batching是完整自动停止的,不需求也无法停止任何干预,关于顶点数在300以内的可挪动物体,只需运用相同的材质,就会组成Batch。Static Batching则需求把静止的物体标志为Static,然后无论大小,都会组成Batch。如前文所说,Static Batching显然比Dynamic Batching要高效得多,于是,Static Batching功用是收费的……
 
要有效应用Draw Call Batching,首先是尽量减少场景中运用的材质数量,即尽量共享材质,关于仅纹理不同的材质能够把纹理组合到一张更大的纹理中(称为Texture Atlasing)。然后是把不会挪动的物体标志为Static。此外还能够经过CombineChildren脚本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手动把物体组合在一同,但这个脚本会影响可见性测试,由于组合在一同的物体一直会被看作一个物体,从而会增加GPU要处置的几何体数量,因而要当心运用。
 
关于复杂的静态场景,还能够思索自行设计遮挡剔除算法,减少可见的物体数量同时也能够减少Draw Call。
 
总之,了解Draw Call和Draw Call Batching原理,依据场景特性设计相应的计划来尽量减少Draw Call次数才是霸道,其它方面亦然。
 
Draw Call Batching (绘制调用批处置)
 
To draw an object on the screen, the engine has to issue a draw call to the graphics API (OpenGL ES in the case of iOS). Every single draw call requires a significant amount of work on the part of the graphics API, causing significant performance overhead on the CPU side.
在屏幕上渲染物体,引擎需求发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES)。
每个绘制调用需求停止大量的工作来访问图形API,从而招致了CPU方面显着的性能开支。
 
Unity combines a number of objects at runtime and draws them together with a single draw call. This operation is called "batching". The more objects Unity can batch together, the better rendering performance you will get.
Unity在运转时能够将一些物体停止兼并,从而用一个绘制调用来渲染他们。这一操作,我们称之为“批处置”。
普通来说,Unity批处置的物体越多,你就会得到越好的渲染性能。
 
Built-in batching support in Unity has significant benefit over simply combining geometry in the modeling tool (or using theCombineChildren script from the Standard Assets package). Batching in Unity happensafter visibility determination step. The engine does culling on each object individually, and the amount of rendered geometry is going to be the same as without batching. Combining geometry in the modeling tool, on the other hand, prevents effecient culling and results in much higher amount of geometry being rendered.
Unity中内建的批处置机制所到达的效果要明显强于运用几何建模工具(或运用Standard Assets包中的CombineChildren脚本)的批处置效果。
这是由于,Unity引擎的批处置操作是在物体的可视裁剪操作之后停止的。
Unity先对每个物体停止裁剪,然后再停止批处置,这样能够使渲染的几何总量在批处置前后坚持不变。
但是,运用几何建模工具来拼合物体,会阻碍引擎对其停止有效的裁剪操作,从而招致引擎需求渲染更多的几何面片。
 
Materials
材质
 
Only objects sharing the same material can be batched together. Therefore, if you want to achieve good batching, you need to share as many materials among different objects as possible.
只要具有相同材质的物体才能够停止批处置。
因而,假如你想要得到良好的批处置效果,你需求在程序中尽可能地复用材质和物体。
 
If you have two identical materials which differ only in textures, you can combine those textures into a single big texture - a process often calledtexture atlasing. Once textures are in the same atlas, you can use single material instead.
假如你的两个材质仅仅是纹理不同,那么你能够经过 纹理拼合 操作来将这两张纹理拼合成一张大的纹理。
一旦纹理拼合在一同,你就能够运用这个单一材质来替代之前的两个材质了。
 
If you need to access shared material properties from the scripts, then it is important to note that modifyingRenderer.material will create a copy of the material. Instead, you should useRenderer.sharedMaterial to keep material shared.
假如你需求经过脚原本访问复用材质属性,那么值得留意的是改动Renderer.material将会形成一份材质的拷贝。
因而,你应该运用Renderer.sharedMaterial来保证材质的共享状态。
 
Dynamic Batching
动态批处置
 
Unity can automatically batch moving objects into the same draw call if they share the same material.
假如动态物体共用着相同的材质,那么Unity会自动对这些物体停止批处置。
 
Dynamic batching is done automatically and does not require any additional effort on your side.
动态批处置操作是自动完成的,并不需求你停止额外的操作。
 
Tips:
提示:
 
1、Batching dynamic objects has certain overheadper vertex, so batching is applied only to meshes containing less than900 vertex attributes in total.
批处置动态物体需求在每个顶点上停止一定的开支,所以动态批处置仅支持小于900顶点的网格物体。
 
2、If your shader is using Vertex Position, Normal and single UV, then you can batch up to 300 verts and if your shader is using Vertex Position, Normal, UV0, UV1 and Tangent, then only 180 verts.
Please note: attribute count limit might be changed in future
假如你的着色器运用顶点位置,法线和UV值三种属性,那么你只能批处置300顶点以下的物体;
假如你的着色器需求运用顶点位置,法线,UV0,UV1和切向量,那你只能批处置180顶点以下的物体。
请留意:属性数量的限制可能会在未来停止改动。
 
4、Don’t use scale. Objects with scale (1,1,1) and (2,2,2) won’t batch.
不要运用缩放尺度(scale)。分别具有缩放尺度(1,1,1)和(2,2,2)的两个物体将不会停止批处置。
 
5、Uniformly scaled objects won’t be batched with non-uniformly scaled ones.
统一缩放尺度的物体不会与非统一缩放尺度的物体停止批处置。
Objects with scale (1,1,1) and (1,2,1) won’t be batched. On the other hand (1,2,1) and (1,3,1) will be.
运用缩放尺度(1,1,1)和 (1,2,1)的两个物体将不会停止批处置,但是运用缩放尺度(1,2,1)和(1,3,1)的两个物体将能够停止批处置。
 
6、Using different material instances will cause batching to fail.
运用不同材质的实例化物体(instance)将会招致批处置失败。
 
7、Objects with lightmaps have additional (hidden) material parameter: offset/scale in lightmap, so lightmapped objects won’t be batched (unless they point to same portions of lightmap)
具有lightmap的物体含有额外(躲藏)的材质属性,比方:lightmap的偏移和缩放系数等。所以,具有lightmap的物体将不会停止批处置(除非他们指向lightmap的同一局部)。
 
8、Multi-pass shaders will break batching. E.g. Almost all unity shaders supports several lights in forward rendering, effectively doing additional pass for them
多通道的shader会阻碍批处置操作。比方,简直unity中一切的着色器在前向渲染中都支持多个光源,并为它们有效地开拓多个通道。
 
9、Using instances of a prefab automatically are using the same mesh and material.
预设体的实例会自动地运用相同的网格模型和材质。
 
Static Batching
静态批处置
 
Static batching, on the other hand, allows the engine to reduce draw calls for geometry of any size (provided it does not move and shares the same material). Static batching is significantly more efficient than dynamic batching. You should choose static batching as it will require less CPU power.
相对而言,静态批处置操作允许引擎对恣意大小的几何物体停止批处置操作来降低绘制调用(只需这些物体不挪动,并且具有相同的材质)。因而,静态批处置比动态批处置愈加有效,你应该尽量低运用它,由于它需求更少的CPU开支。
 
In order to take advantage of static batching, you need explicitly specify that certain objects are static and willnot move, rotate or scale in the game. To do so, you can mark objects as static using the Static checkbox in the Inspector:
为了更好地运用静态批处置,你需求明白指出哪些物体是静止的,并且在游戏中永远不会挪动、旋转和缩放。想完成这一步,你只需求在检测器(Inspector)中将Static复选框打勾即可,如下图所示:
 
Using static batching will require additional memory for storing the combined geometry. If several objects shared the same geometry before static batching, then a copy of geometry will be created for each object, either in the Editor or at runtime. This might not always be a good idea - sometimes you will have to sacrifice rendering performance by avoiding static batching for some objects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.
运用静态批处置操作需求额外的内存开支来贮存兼并后的几何数据。在静态批处置之前,假如一些物体共用了同样的几何数据,那么引擎会在编辑以及运转状态对每个物体创立一个几何数据的备份。这并不总是一个好的想法,由于有时分,你将不得不牺牲一点渲染性能来避免一些物体的静态批处置,从而坚持较少的内存开支。比方,将浓密森里中树设为Static,会招致严重的内存开支。
 
Static batching is only available in Unity iOS Advanced.
静态批处置目前只支持Unity iOS Advanced。
 
备注:最近不断在研讨Unity3D的性能优化问题,这段时间可能会多翻译这方面的文章。
 
前两天,MadFinger,就是当今iOS与Android上画质最牛逼闪闪的游戏之一——ShadowGun的开发商,令人惊异地放出了一个ShadowGun的样例关卡以及若干可免费运用的Shader,国外同行们的分享肉体真的是令人赞赏不已。原文在这里,以下是我的一些摘录和笔记。
 
首先是一些优化常识。针对图形方面的优化主要包括三角形数量,纹理所占内存,以及Shader,前两项根本没什么好讲的,针对设备机能的限制制定相应的指标即可,所以Shader就成为了图形性能优化的关键。
 
Alpha blending
 
在Unity官方文档中讲,由于硬件缘由,在iOS设备上运用alpha-test会形成很大的性能开支,应尽量运用alpha-blend替代。这里提到,在同屏运用alpha-blend的面数,特别是这些面所占屏幕面积的大小,对性能也会形成很大影响。缘由是运用alpha-blend的面会形成overdraw的增加,这特别对低性能设备的影响很大。不过没有购置Pro版,没有Occlusion Culling功用的话,就不用顾忌这一问题了,反正overdraw是必然的。
 
复杂的Per-pixel shader
 
Per-pixel shader即Fragment shader,望文生义是要对每个渲染到屏幕上的像素做处置的shader,假如per-pixel shader比拟复杂且需求处置的像素很多时,也就是运用该shader的面占屏幕面积很大时,对性能的影响以至要超越alpha blending。因而复杂的per-pixel shader只适用于小物体。
 
下面是常州微信公众平台对几个Shader的逐一解说:
 
Environment specular maps(Shader Virtual Gloss Per Vertex Additive)
Specular map通常都是应用贴图的alpha通道来定义物体外表的润滑水平(反光度),这个shader的特性是per-vertex计算反光度的,有着相当不错的效果的同时比per-pixel的shader性能要高得多。这个shader很适用于关卡环境等占很大区域的模型。
 
经过优化的动态角色光照和阴影(Light probes和BRDF Shader)
传统的Lightmaps无法支持动态物体,对此Unity提供了Light probes技术,预先把动态物体的光照信息保管在代理对象(即Light probes)中,运转时动态物体从间隔最近的Probe中获取光照信息。
 
Unity自身还提供了一个效果十分棒的专为挪动设备优化过的角色Shader,支持Diffuse、Specular和Normal maps,并经过一个特殊的脚本生成贴图用于模拟BRDF光照效果。最终产生的效果堪比次时期大作中的角色光影效果。
 
雾和体积光(Shader Blinking Godrays)
目前在挪动设备上要开启真正的雾效根本不可行,ShadowGun的计划是经过简单的网格+透明贴图(称为雾面)来模仿雾效。在玩家靠近时,雾面逐步变淡,同时fog plane的顶点也会移开(即便完整透明的alpha面也会耗费很多渲染时间)。
 
运用这个Shader的网格需求经过处置:
顶点的alpha值用于决议顶点能否能够挪动(在例子中0为不可动,1为可动)。
顶点法线决议挪动的方向
然后Shader经过计算与察看者的间隔来控制雾面的淡入/淡出。
这个Shader还能够用来做体积光和其它一些alpha效果。
飞机坠毁的浓烟效果(Shader Scroll 2 Layers Sine Alpha-blended)
 
经过粒子产生浓烟的代价太高,所以ShadowGun中运用了网格+贴图动画来制造这个效果。经过混合两层贴图并让它们交织挪动来产生动画效果。其中顶点alpha值用于让网格的边缘看起来比拟温和,同时运用顶点颜色来模仿从火焰到烟雾的过渡效果。
 
带动态效果的天空盒(Shader Scroll 2 Layers Multiplicative)
经过两张贴图的混合和挪动产生云的动态效果。
 
旗帜和衣服的飘动效果(Shader Lightmap + Wind)
同样应用顶点alpha值决议哪些顶点能够挪动,然后shader的参数用于调整摆动的方向和速度。
 
一、程序方面
 
01、务必删除脚本中为空或不需求的默许办法;
02、只在一个脚本中运用OnGUI办法;
03、防止在OnGUI中对变量、办法停止更新、赋值,输出变量倡议在Update内;
04、同一脚本中频繁运用的变量倡议声明其为全局变量,脚本之间频繁调用的变量或办法倡议声明为全局静态变量或办法;
05、不要去频繁获取组件,将其声明为全局变量;
06、数组、汇合类元素优先运用Array,其次是List;
07、脚本在不运用时脚本禁用之,需求时再启用;
08、能够运用Ray来替代OnMouseXXX类办法;
09、需求躲藏/显现或实例化来回切换的对象,尽量不要运用SetActiveRecursively或active,而运用将对象远远移出相机范围和移回原位的做法;
10、尽量少用模运算和除法运算,比方a/5f,一定要写成a*0.2f。
11、关于不经常调用或更改的变量或办法倡议运用Coroutines & Yield;
12、尽量直接声明脚本变量,而不运用GetComponent来获取脚本;
iPhone
13、尽量运用整数数字,由于iPhone的浮点数计算才能很差;
14、不要运用原生的GUI办法;
15、不要实例化(Instantiate)对象,事前建好对象池,并运用Translate“生成”对象;
 
二、模型方面
 
01、兼并运用同贴图的材质球,兼并运用相同材质球的Mesh;
02、角色的贴图和材质球只需一个,若必需多个则将模型离别离为多个局部;
02、骨骼系统不要运用太多;
03、当运用多角色时,将动画单独别离出来;
04、运用层间隔来控制模型的显现间隔;
05、阴影其实包含两方面暗淡和影子,倡议运用实时影子时把暗淡效果烘焙出来,不要运用灯光来调理光线暗淡。
06、少用像素灯和运用像素灯的Shader;
07、假如硬阴影能够处理问题就不要用软阴影,并且运用不影响效果的低分辨率阴影;
08、实时阴影很耗性能,尽量减小产生阴影的间隔;
09、允许的话在大场景中运用线性雾,这样能够使远间隔对象或阴影不易发觉,因而能够经过减小相机和阴影间隔来进步性能;
10、运用世故组来尽量减少模型的面数;
11、项目中假如没有灯光或对象在挪动那么就不要运用实时灯光;
12、水面、镜子等实时反射/折射的效果单独放在Water图层中,并且依据其实时反射/折射的范围来调整;
13、碰撞对效率的影响很小,但碰撞还是倡议运用Box、Sphere碰撞体;
14、建材质球时尽量思索运用Substance;
15、尽量将一切的实时反射/折射(如水面、镜子、地板等等)都汇合成一个面;
16、假反射/折射没有必要运用过大分辨率,普通64*64就能够,不倡议超越256*256;
17、需求更改的材质球,倡议实例化一个,而不是运用公共的材质球;
18、将不须射线或碰撞事情的对象置于IgnoreRaycast图层;
19、将水面或相似效果置于Water图层
20、将透明通道的对象置于TransparentFX图层;
21、养成良好的标签(Tags)、层次(Hieratchy)和图层(Layer)的条理化习气,将不同的对象置于不同的标签或图层,三者有效的分离将很便当的按称号、类别和属性来查找;
22、经过Stats和Profile查看对效率影响最大的方面或对象,或者运用禁用局部模型的方式查看问题到底在哪儿;
23、运用遮挡剔除(Occlusion Culling)处置大场景,一种较原生的类LOD技术,并且可以“分割”作为整体的一个模型。

上篇:上一篇:Unity5.x Reflection Probe引见
下篇:下一篇:常州手游开发-UGUI屏幕自顺应