Unity性能优化概要

一.项目概览

        1.检查资源的环境情况:在Project中通过Search By Type查看资源分布情况

        2.关注场景中的摄像机数量(影响渲染流程的复杂度)与灯光数量(影响光照与阴影复杂度)

        3.运行游戏后,点击Stats观察渲染信息,如图下所示:

        注: Tris为三角面数,Verts为顶点数

二.静态资源的优化

        1.Unity Assets 工作流程图

                导入 > 创建 > 构建 > 分发 > 加载

        2.资源类型

                1.外部导入资源:模型网格,纹理,音乐音效,动画等

                2.内部创建资源:预制体,Timeline,VFX等

               导入设置资源规格影响性能

        3.静态优化分析工具

                1.进入Unity UPR网页

                2.创建新的项目(项目包名在Project Settings > Player > Package Name)

                3.通过解压AssetChecker并且通过Win+R(输入命令:cd /d AssetChecker所在路径)

                4.输入命令:assetcheck.exe --project="project_path" --projectId="project_id"

        4.音频优化

                1.Force To Mono:如果左右声道相同可以开启此选项,使得双声道变为单声道。

                2.Compression Format:长时间音频使用Vorbis(压缩但保真),短时间音频使用      ADPCM(压缩但不保真)。

                3.Sample Rate Setting(Override Sample Rate):修改默认音频采样率,一般移动平台为22050Hz。

                4.Load Type:

                        1)Decompress On Load:音频资源小于200KB。​​​

                        2)Compressed In Memory:较大的复杂音频。

                        3)Streaming:长度较长的音效或者背景音乐,但会增加CPU开销。

                5.注意:实现静音功能时,应该直接销毁AudioSource组件,将音频从内存中卸载。

        5.模型优化

                1.DCC工具模型导出概要

                        1)统一数据

                        2)导出网格必须是多边形拓扑

                        3)导出前确保所有Deformers全部烘培到网格模型上

                        4)原始模型尽量少的材质,网格,骨骼数,并且导出时FK与IK节点分离

                           (Unity不支持导入IK骨骼节点,所以导出前需要删除)

                        注意:不建议模型使用的纹理随着模型一并导出;不建议导出携带场景信息。

                2.Unity模型设置概要

                        1)Scene >Import XXX可以选择不开启

                        2)Meshes >Read/Write 一般不开启(除非运行时动态修改网格或蒙皮网格动画)

                        注:开启此选项会在内存中额外复制一份,分别保存在内存与显存中。

                        3)Geometry >Index Format(16bit):模型顶点少于65535个可开启,否则      Auto。

                        4)如果模型无动画可以设置Animation >Import Animation关闭。

        6.纹理优化

                1.纹理概要

                        1.常用纹理类型:

                                1)Default:默认纹理

                                2)Normal map:法线贴图

                                3)Sprite(2D and UI):使用2D Sprite或者UGUI

                                4)Lightmap:光照贴图

                                5)Single Channel:如果原始图片只有一个通道,则选此类型(节省内存)

                        2.纹理大小

                        Mipmap(分级细化纹理):类似于图片LOD,但不需要额外生成对象

                        :纹理小欠采样模糊,纹理大过采样噪点。

                        3.纹理色彩空间

                        金属贴图,粗糙度贴图,法线贴图等(不用做颜色信息)不适用sRGB色彩空间。

                        4.纹理压缩

                        一般使用硬件(GPU)支持的纹理压缩格式(ASTC,ETC2等)。

                        5.纹理图集(一系列小纹理图像的集合)

                        6.纹理过滤

                                1)Point(No Filter):计算量最少但近距离纹理呈现块状。

                                2)Bilinear(双线性):像素平滑渐变但近距离纹理模糊。

                                3)Trilinear(三线性):平滑过渡Mipmap明显变化。

                                4)Anisotropic Filtering(各向异性过滤):适用于地表纹理。

                2.纹理设置与优化

                        1.设置

                                1)Alpha Is Transparency:如果非半透明,关闭此选项。

                                2)Generate Mip Maps:除2D与固定视角游戏外,都建议开启。

                                3)Filter Mode:选择双线性2x各向异性过滤,有选择地使用三线性。

                                4)Fromat:无

                        2.优化思路

                                1)将类似生命周期的小纹理放在同一纹理图集中

                                2)设计时应该避免大面积的半透明纹理

                                3)将序列帧动画放入纹理图集

                                3)颜色渐变(黑白)贴图采用单通道压缩

                        :判断纹理是否为单通道与查看Mip Map各级别情况

                        贴图上方点按R,G,B如果只有一个有画面则可以设置单通道,上方右侧即为Mip                          Map级别显示图样查看。

        7.动画优化

                1)有动画文件的模型导入:需要开启模型Rig中Animation Type选择Generic(通用骨  骼)或Humanoid(人形骨骼),若需要重定向或者IK使用人形骨骼,否则使用通用骨骼(减少CPU运算)。

                2)Rig >Optimize Bones:建议开启,剔除没蒙皮顶点的骨骼。

                3)Rig >Skin Weight:对于不重要的动画对象,可以减少为1根。

                4)Animation >Anim.Compression:一般选择Keyframe Reduction

                :开启压缩,会有XXX Error选项,减少Error可以提升动画精度(细节),幅度与体积越大,误差会被放大。

                总结:优化应注意效果差异,动画曲线数量(数量越少并以常量曲线为主越好)与动画文件大小(一般不超过1M)。

三.工作流优化

        1.Unity工程目录结构

                1)Asset文件夹:项目资产

                2)Library文件夹:项目内部资源数据信息

                注:如果编辑器使用出现问题,可以删除重新生成。

                3)Packages文件夹:项目包文件信息

                4)Project Settings文件夹:项目设置信息

                5)UserSettings文件夹:用户设置信息

                6)Temp(临时数据)与Logs(日志信息)文件夹

        2.Assets目录中Resources文件通常是Unity项目性能问题的主要来源,尽量使用Assets        Bundle方式进行构建和加载资源。

        3.Assets目录结构设计

                1)一级目录:区分编辑器与运行模式,区分工程大版本,例如:场景,设置,游                                                    戏运行,编辑器,脚本等。

                2)二级目录:区分资源类型(预制体,特效,动画,贴图等)。

                3)三级目录:资源子类型下的区别。

                4)四级目录:只有Audio/Texture/Models做四级划分,按模块或者生命周期划分。

四.编辑器优化

        1.场景资源优化

                1)避免场景节点深度太深。

                2)尽量使用Prefab节点构建场景(内存不变,只需要引用即可)

                3)避免DontDestroyOnLoad(或者添加Hidden Flag Dont Sale标记的资源对象)下太  多生命周期过长或者引用过多资源的复杂对象。

                4)给经常使用的对象添加Tag,静态对象(运行时不移动的对象)添加Static标记。

                FindGameObjectWithTag是效率最高的方法寻找场景对象。

        2.预制体优化

                1.嵌套预制体(嵌套关系)

                :不适用大规模远景对象,会增加材质与Drawcall数量。

                2.预制体变体(父子关系)

                        1)特点:变体只是预制体的实例;不能改变与删除Prefab(父)

                :右击预制体Create > Prefab Variant创建预制体变体。

                3.Drawcall:

                        1)概念:CPU调用图像编程接口,(CPU)调用Drawcall命令开启一个(GPU)渲染过程。

                        2)减少Drawcall的方式:批处理(把多个小Drawcall合并成一个Drawcall),减少CPU提交的次数与时间,并且怕批处理适合静态物体

        3.UGUI优化

                1.UGUI渲染细节

                        1)绘制顺序是从后往前,很难保证每个像素不被重新绘制

                        2)若UI SpriteAtlas图集利用率不高,则大量完全透明的像素被采样也会导致重新绘制,导致纹理采样器无法尽快采样有效像素。

                2.Canves优化

                        1)避免UI元素重叠

                        2)拆分使用Canves或者嵌套使用Canves(用来减少Re-batch复杂度)

                        3)拆分动态与静态对象,分别放入不同Canves

                        4)尽量不使用Layout组件(减少Layout Re-build)

                        5)Canves的RenderMode尽量使用Overlay模式(减少Camera调用开销)

                3.射线检测优化

                        1)必要交互UI开启Reycast Target(非必要不开启)

                        2)对于复杂控件,尽量在根节点开启Reycast Target

                        3)对于嵌套的子Canves,开启OverrideSorting会打断射线向父级Canves传递

                4.UI字体文件导入优化

                        1)Rendering Mode一般选择Smooth即可

                        2)Character:除Dynamic,其余均为静态字符集

                        3)Include Font Data:使用对应运行平台操作系统已有字符,则不勾选此选项(                                  减少内存空间)

                5.UI字体优化

                        1)利用不多的特殊字体可以使用图片或者Custom Font(自定义图片字体)

                        2)利用Font.RequestCharacterInTexture(字符串)可以预载需要字体到图集

                        :运行时,UIText组件会动态生成字体图集(只会保留激活的组件中的字符)

                6.UI组件优化

                        1)UI元素如果可以拉伸,则减少UI Sprite大小

                        2)对于UI显隐,不使用控制透明度或者激活/关闭,而去控制Canves的激活/关闭

                        3)使用全屏UI,需要隐藏背后所有内容

                        4)在对话中时UI建议使用OnDemandRendering.renderFrameInterval = n(将渲染降低至原有的1/n) 对渲染进行降频

                        :不使用Target FPS,因为会对输入也降频

                补充:对于Scroll View使用RectMask2D组件裁剪,使用对象池作为实例化缓存。

                        :RectMask2D组件会限制子物体的显示范围。

        4.物理优化

                1.物理解决方案:Box2D(2D通用开源框架), Nvidia PhysX(非确定性,硬件加速,不适用网络游戏 ) , Unity Physics(基础), Havok Physics for Unity 

                2.项目中Physics设置:

                        1)Reuse Collision Callbacks:一般建议开启,会降低托管堆GC开销。

                        2)Defult Solver(Velocity)Iterations:一般默认,设置迭代次数,提高精度。

                        3)Boradphyase Type:一般默认,对场景划分,加速物理查找。

                3.项目中Time设置:

                        1.可以调整Fixed Timestep,降低更新频率,提高性能。

                                1)副作用:无法检测物理碰撞。

                                2)解决方案:利用射线作为高速物体的碰撞检测;利用两个渲染帧的物体位置做一个包裹盒检测物理碰撞。

                        :物理更新是在FixUpdate中完成的。

                4.Collider:进行碰撞检测,Trigger对象不需要Rigibody组件。

                        优化:1)使用简单的 Collider,用多个简单的代替Mesh Collider(三角形碰撞)

                                   2)Mesh Collider尽量保证物体静态。

                                   3)在PlayerSetting中开启Prebake Collision Meshes, 预先烘培碰撞网格。

                5.Rigibody:进行碰撞模拟,Rigibody对象越少越好。

                        1)Kinematic: 不受力影响,当对其他Rigibody施加物理影响。

                        2)Rigibody:完全由物理引擎模拟。

                6.RayCast与Overlap

                        1)使用NoAlloc版本的函数,较少GC(垃圾回收)开销。

                        2)指定对象图层进行过滤,指定RayCast距离。

                        3)如果大量使用RayCast操作可以通过RaycastCommand的方式批量处理,利用JobSystem来分摊到多核多线程计算。

        5.动画优化

                1.Animator

                        1)不使用字符串查询Animator。

                        2)使用曲线标记来处理动画事件。

                        3)使用Target Marching函数(目标点匹配)协助处理动画。

                        4)将Animator的CullingMode设置为Cull Update Transform,并禁用SkinMesh Renderer组件的Update When Offscrren使得角色不可见时不更新动画。

                :状态机会将所有的动画节点全部载入内存,开销较大。

                2.Animation

                        1)CPU核数少时,可以使用Animation播放动画。

                        2)动画曲线较少时,使用Animation。

                        3)将Animation的CullingMode设置为Base On Renderers

                3.Playable(自定义程度更高,优化的效果更好)

                4.动画方案的选择:

                        1)简单少量曲线动画使用Animation

                        2)动画要求与逻辑要求较高,并且动画资源不多使用Animator Graph(状态机)

                        3)动画混合要求高,需要高级动画效果(技能编辑器等)并且动画资源多,采用AnimatorPlayable API扩展Timeline的方式完成。

五.项目优化理论

        1.剔除(Culling)

                1.剔除内容:看不到的像素,网格与对象;重复且无用的资源;无用且不执行的代码

                2.Unity中的剔除方案:

                        1)像素剔除:摄像机平截头体剔除,Bake-face Culling,Early-Z,Pre-Z Pass

                        2)网格剔除:Layer Mask,可见距离剔除,Occlusion(CPU + 烘培)

                        3)灯光剔除:Tile-Based Deferred Rendering,Forward +

                        4)场景剔除:Additive Scene

        2.简化(Simplization)

                1.简化内容:运行效率较重的资源,低效和不合适的功能

                2.Unity中的简化方案:

                        1)Quality Settings的质量分级

                        2)烘培光照代替实时光照

                        3)简化碰撞体代替Mesh碰撞

                        4)Local Volume代替Global Volume

                        5)RayCast代替SphereCast等

                        6)纹理文字代替系统文字

                        7)Mesh/Shader/HL  OD

        3.合批(Batching)

                1.资源Batching(Mesh,Texture,Shader参数,材质属性)

                2.Draw call Batching(Static Batching,Dynamic Batching)

                3.GPU Instancing(直接渲染,间接渲染,程序化间接渲染)

                4.Set Pass Call Batching(SRP Batching)

六.项目优化实践

        1.优化总述

·                1.性能优化流程

                        1)发现问题:平台,操作系统,问题发生的前提情况,一般性还是特殊性问题

                        2)定位问题:造成问题的位置,确定瓶颈

                        3)研究问题:确定方案处理问题

                        4)解决问题:验证处理结果与预期的一致性

                2.影响性能的主要问题

                        1)CPU(工厂1)

                        2)GPU(工厂2)

                        3)带宽(连通道路)

                        4)内存(仓库)

                        5)隐形问题:功耗比(相同效果的消耗量),填充率(传输数据的填充度),发    热率(设备发热带来的降频影响)

                3.性能问题的可能情况(由高到低):

                        CPU利用率 >带宽利用率 >CPU/GPU强制同步 >片元着色器 >几何图形(纹理)在CPU与GPU传输 >顶点着色器 >几何图形的复杂性

                4.优化思路:

                        1)升维(算法复杂,优化好)/降维(算法简单,优化差)

                        2)维度转换(面向对象与面向数据的转化等)

                        3)空间与时间的取舍(TAA与DLSS等)

                        4)量纲转换

        2.性能总览与瓶颈定位

                1.Unity Profiler中常见的标记:

                        1)WaitForTargetFPS:等待达到目标帧率(一般CPU与GPU都没负载问题)

                        2)Gfx.WaitForGfxCommandsFromMainThread/WaitForCommand:渲染线程准                                  备接受新的渲染命令(一般瓶颈在CPU)

                        3)Gfx.WaitForPresentOnGfxThread/WaitForPresent:主线程等待渲染线程绘制                                  完成(一般瓶颈在GPU)

                        4)WaitForJobGroupID:等待工作线程完成(一般瓶颈在CPU)

                2.Unity UPR工具

                        在电脑端安装UPR Desktop,然后在UPR网页中我的项目,创建测试项目,在测试列表中新建测试,并复制Session Id给UPR Desktop,然后将测试设备与电脑连接(或者连接在相同的wifi环境下),输入测试设备的IP地址,然后打开游戏,再点击开始测试,一段时间后结束在网页中就会生成相关检测报告

        3.SSAO优化

                1.概述:

                        SSAO在URP文件中进行设置,并且可更改Rendering Path:前向渲染与延迟渲染

                2.设置调整:

                        1)Method:一般选Interleaved Gradient,计算更快,相机静止不会出现扰动。

                        2)Radius(采样半径):一般设置为0.1即可,数值越大,性能消耗越大。

                        3)Falloff Distance:场景物体较多时影响较大,可以适度降低。

                        4)Quality >Source:如果是延迟渲染则无法调整,正向渲染一般默认即可。

                        :延迟渲染会大幅降低渲染成本,但并不是所有平台兼容。

                        5)Downsample:建议开启,处理像素会变为原来1/4,大幅降低GPU性能

                        6)After Opaque:虽然会造成非真实的渲染,但一般情况下建议开启

                        7)Blur Qulity(模糊质量)与Sample(采样数):建议开启Medium或Low即可

                3.其余优化方案:

                        1)使用HBAO(采样更少)或GTAO(采样更少且效果好)代替SSAO。

                        2)针对SSAO的Shader指令进一步优化。

                        3)采用烘培AO到光照贴图的方案。

        4.AA反走样优化

                注:MSAA在URP文件中,SMAA在摄像机设置中

                1.MSAA:仅支持前向渲染,显卡硬件支持,效果较好,运动画面一般。

                2.FXAA:开销小,适合移动平台,动态场景闪烁问题。

                3.SMAA:开销较小,适合低端PC端,效果好于FXAA。

                4.TAA:支持延迟渲染,效果较好,性能开销低,低帧率鬼影问题。

                5.优化方案

                        1)高端设备采用SMAA或者TAA

                        2)中端设备采用FXAA

                        3)低端设备建议关闭AA渲染

                        4)一般不需要同时开启MSAA与其余后处理层面的反走样。

        5.后处理优化

                1.在URP文件的Post-processing设置

                        1)Grading Mode:支持浮点精度纹理的设备选择HDR,否则选择LDR

                        2)LUT size:在LDR选项下可以修改为16

                        3)Fast sRGB/Linear convesions:建议开启

                2.影响性能较大的后处理效果:Bloom(泛光)【降低采样和迭代次数】,Depth Of Field(景深)【切换Guassian(高斯)和Bokeh的景深模式】,Motion Blur(运动模糊),Lens Flare(镜头光晕)【Occlusion设置与光晕优化】

                3.优化建议:一般不使用后处理,尽量使得原始素材就接近所需要的表现效果,如果必须使用则,尽量不要使用Global,而是使用Local,而且不要堆叠过多后处理效果,应该使用脚本有目的地开启与关闭。

        6.场景简化

                1.远景简化

                如果远景(玩家无法到达)是使用真实模型搭建,可以使用反射探针(Static旁朝下三角改为Reflection Probe Static)烘培一张只有远景模型的贴图(Convolution Type改为None),再将这张贴图赋给SkyBox/CubMap材质,最后将材质给予环境中的天空盒

                2.中景简化

                调整LOD的显示范围,并且可以酌情关闭低LOD模型的阴影(Cast Shadow 改为Off),调整规则就是大物体可以减少直接裁剪的距离,但需要多个LOD模型均匀分布,而小物体则可以增加直接裁剪的距离并且关闭LOD阴影,LOD数量可以只有1个。

                调整Project Settings中Quality的LOD Bias,大于1,保留更多细节;小于1,更激进剔除

        7.遮挡剔除与光影剔除

                1.遮挡剔除

                        1)开启摄像机中的Occlusion Culling

                        2)静态遮挡物(墙壁等)Static旁边倒三角选择Occluder Static,静态被遮挡物体(墙壁之后的物体等)选择Occludee Static

                        3)打开Occlusion窗口点击烘焙即可。

                        注:若遮挡物为动态物体(门窗等),可以加入Occlusion Proto 组件,通过脚本进行逻辑控制即可(函数延时实现)。

                2.光源剔除

                        方法一:可以通过设置Rendering Layer调整光源渲染层级(详见Unity手册)

                        方法二:设置URP管线文件:

                                1)Render Limit(每个对象最大能接受几个光源影响)

                                2)可以调小Shadow Atlas Resolution与Shadow Resolution Tiers的值

                                3)调小Cascade Count的值(可以减少远距离细小阴影的个数)

        8.地形优化

                由于Unity提供的地形方案对移动端并不友好,可以采用插件进行地形绘制。

        9.移动平台耗电量与发电量优化

                移动平台存在温度墙,一旦温度过高就会降频处理,移动平台优化应该尽量拖迟触发温度墙的时间以及减少降频时间

                1.常规优化

                        锁60FPS时,CPU可10~12ms,GPU可6~8ms

                        锁30FPS时,CPU可18~20ms,GPU可8~10ms

                        注:移动平台可以放宽CPU限制,收紧GPU限制。

                2.非常规优化

                        1)网络与IO:发包频率与频繁的IO读写。

                        2)显示亮度与FPS:动态分辨率,亮度与帧率限制。

        10.启动时间优化

                IOS平台与安卓平台启动App的过程不同,需要不同的优化手段。

由于能力有限,部分内容(Shader,IO,GC,网络等)无法很好理解,所以不做笔记。

注:未完成内容包括渲染流程精简,内存优化,主光源级联阴影优化,移动端打包与启动优化。

猜你喜欢

转载自blog.csdn.net/stariser/article/details/146520404
今日推荐