封面来源:A Cold Stop(Mixer 制作材质、UE4渲染 )

[UE4]性能优化指南(美术向)玄冬Wong:[UE4]性能优化指南(美术向)​zhuanlan.zhihu.com

内容都是处理项目问题的相关笔记,留给自己做备忘录,也分享出来让别人少走弯路。

零散记录GPUProfile来统计性能消耗的时候,在editor模式下不是很准,因为编辑器的消耗也算进去了,如果要用,最好以Game模式来查看。

UE4不支持640X480的分辨率,如果在这个分辨率下运行程序,会导致程序崩溃(4.4版本,不知最新版本是否仍有此问题)。

如果角色身上有很多Component需要Attach,尽量在使用时Attach,不要一加载就全部attach,否则当场景中角色很多时,会有严重性能问题。

比如:场景中有几百个角色,但不是每个角色都需要摄像机和弹簧臂,那么在构造函数中就不要创建摄像机和弹簧臂组件。

面数对UE4来说不敏感,即使在移动端。ipad 4上,50万的三角面,也能够以30fps帧率稳定运行,移动端主要对贴图大小、材质复杂度较为敏感。

代码编译优化C++ 比 蓝图快100到1000倍

[Test] Blueprint vs C++ Performance vs Nativized BP

https://www.reddit.com/r/unrealengine/comments/6qtxy3/test_blueprint_vs_c_performance_vs_nativized_bp/

感谢知乎网友金木研指正:以上结果是在编辑器模式下的测试结果(没有native蓝图),如果打包并将蓝图转换为native code,那么蓝图和C++的性能差距不超过两倍。

使用C++进行向量变换时,尽量使用FTransform::TransformXXX()和FTransform::InverseTransformXXX,而不是FQuat::RotateVector和FQuat::UnrotateVector,因为前者使用了更多的当前硬件支持的矢量汇编指令,榨干了硬件性能,而后者是为了跨平台,老老实实使用C++代码来执行计算公式,虽然也调用了硬件汇编指令,但数量相对较少。

UE4做了优化,当你使用FTransform::TransformXXX()时,如果当前硬件支持(intel 2008年之后的CPU、AMD 2011年之后的CPU),就走硬件指令,如果不支持,则走FQuat::RotateVector。

VS2019针对C++代码编译速度、以及CPUAVX/AVX2指令集下的矢量计算进行了更深入的优化,并且微软Xbox ATG团队使用UE4的demo工程Infiltrator对优化后的效果进行了基准测试:

编译速度方面:完整编译速度,VS2019(16.2)是VS2017(15.9)的3.5倍,增量编译速度,VS2019(16.2)是VS2017(15.9)的1.6倍;

代码优化方面:以游戏帧率作为测试标准,VS 16.2相对16.0提升了2%到3%,而16.0相对15.9最大可以提升2.8%,也就是说使用VS2019编译代码,相比VS2017,可以让游戏运行时帧率提升5%左右。更多详情见微软C++团队博客:C++ Team Blog。

如何断点调试UE4中的内联函数:我们知道加了FORCEINLINE的函数无法断点调试,但是FORCEINLINE_DEBUGGABLE可以,这样保证函数既能在debug模式下调试,又能在shipping打包时让函数内联。

代码算法优化(仅限UE4 API相关)清空TArray时,如果该TArray对象还会继续使用,使用Reset()代替Empty(),因为前者不会销毁内存空间。

TArray移除元素时,如果对元素的顺序不关心,可以使用RemoveAtSwap()代替RemoveAt(),前者是用数组末尾的元素来填补内存空洞(移除元素后产生的无效内存空间),而后者是对空洞后的所有元素平移。时间复杂度,前者为O(RemovedCount),后者为O(ArrayNum)。

如果是单个生产者单个消费者(SPSC)的线程环境,可以使用TCircularQueue作为消息队列来保证数据安全,比使用FScopeLock消耗低,因为前者内部使用的是atomic,而非lock(虽然atomic也算一种轻量级lock)。

视距裁剪(剔除)开启Occlusion Culling (Project Settings -> Engine -> Rendering -> Occlusion Culling,默认已开启)。如果需要增大以屏占比基准的剔除强度(代价是剔除效果比较突兀)以提升渲染效率,将以下属性值增大:

Min Screen Radius for Lights

Min Screen Radius for Early Z Pass

Min Screen Radius for Cascaded Shadow Maps

使用Cull Distance Volume进行细粒度的视距裁剪。Project Settings中的Occlusion Culling只能通过一个临界阀值来控制视距裁剪,而Cull Distance Volume可以设置多级裁剪参数。

灯光优化3种光源的性能消耗从低到高:

定向光/平行光(Directional Light) < 点光源(Point Light) < 聚光灯(Spot Light)。

这个标准不局限于UE4,其他引擎也是这样。当光源数量在场景中达到一定量级时,3种灯光的性能差距也是数量级上差距。

Point Light 和 Spot Light 的消耗到底谁高谁低,UE4官方文档上貌似没找到明确解释。可能两种灯光在不同使用场景下,消耗对比也不一样。

Unity早期官方文档给出了两种灯光在GPU上的消耗说明:

Point Light: They have an average cost on the graphics processor (though point light shadows are the most expensive).

Spot Light: They are the most expensive on the graphics processor.

不考虑显存等其他因素的开销,单考虑GPU消耗,Spot Light 比 Point Light贵。

Unity早期文档:灯光 Light http://www.ceeger.com/Components/class-Light.html

感谢知乎网友刘相敬给的指导建议:

“不考虑阴影的情况下点光源的衰减计算比聚光灯简单很多,只和距离相关,射灯要计算距离衰减和内外角衰减,有cos sin指令,代价相对来说会大很多,但是实际使用过程中射灯照亮区域远小于点光源,反而在绝大多数场景消耗比点光源低。当然这个是基于延迟渲染和ClusterBased裁剪后的灯光来说的,实际Unity Forward渲染是不裁剪光源的,所有像素都会计算一遍点光源和射灯光照,所以射灯消耗会远大于点光源(Forward Add中渲染),Unity的默认射灯没有内外角一说,依靠一张贴图来做衰减模拟,所以Unity的射灯比点光源多了一次采样环节。”

在建构光照贴图时,若场景中没有给予Lightmass Importance Volume,会对整个场景做间接光照的采样,产生Indirect Lighting Cache,这对大型游戏场景是相当的浪费,像是游戏角色到不了的中、远景不需要产生Indirect Lighting Cache,这时候就可以在场景中置入Lightmass Importance Volume,指定特定区域内才会产生Indirect Lighting Cache,节省不少建构光照的时间。

点光源和聚光灯尽量不要开启Cast Volumetric Shadow;默认只有平行光开启了此选项。开启后的性能消耗为不开启的性能消耗三倍。不开启表示阴影计算方式使用Shadow Mapping,开启表示使用Shadow Volume,前者的阴影计算没有后者精准,但是计算量小。

如果开启体积雾,建议将灯光改成静态光,这样在Build Lighting时会生成预计算的体积雾相关数据,这样可以显著提升体积雾性能。体积雾性能消耗巨大。

如果场景没有静态光 Static Light(全是动态光 Movable Light 或者固定光 Stationary Light),则要禁用 Static Lighting,以节省 Static Lighting 相关的开销(比如 LightMaps和ShadowMaps的相关计算)。禁用方式:Project Settings -> Engine -> Rendering -> Lighting -> disableAllow Static Lighting。

当全动态灯光为性能瓶颈时,禁用Static Lighting可以提升性能。测试用例:我的某个游戏场景,Lighting是瓶颈之一,r.ScreenPercentage 修改为400进行压力测试,关闭 Static Lighting 后帧率提升了20帧。因为没有静态光,禁用后光影效果亦无任何损失。

关闭Support Global clip plane for Planar Reflections,默认关闭,开启后消耗巨大。

AO性能优化。在超大型场景中,一般灯光会是性能瓶颈之一,特别是动态光场景下。此时关闭AO可以大幅提高帧率(AO默认为开启,早期版本默认是关闭的)。开启AO后(Project Settings -> Engine -> Rendering -> Default Settings ->Ambient Occlusion),引擎默认的AO为SSAO(Screen Space Ambient Occlusion), SSAO无法进行预计算,所以GPU性能开销较大,可以修改为DFAO(Distance Field Ambient Occlusion)以提升性能,因为DFAO可以预计算,代价是增加显存开销。

DFAO开启方式:

Distance Field Ambient Occlusion

https://docs.unrealengine.com/en-us/Engine/Rendering/LightingAndShadows/DistanceFieldAmbientOcclusion

DFAO相关的两个优化选项:

(1) Compress Mesh Distance Fields: 通过压缩Distance Fields volume texture来减少显存占用,代价是当使用Level Streaming时会出现Hitch。

(2) Eight Bit Mesh Distance Fields: 将Distance Fields volume texture从16位格式压缩为8位格式,代价是AO视觉效果变粗燥。

如果场景中有大量点光源和聚光灯且都是动态的,此时通过Distance Field动态地对LightComponent执行SetVisibility和SetHiddenInGame,那么性能可提高30%到60%。这个结论是基于对官方商城一款付费插件Dynamic Lighting Portal System (Performance Booster)的源码研读。引擎本身有对灯光Occlusion Culling,至于为什么SetVisibility和SetHiddenInGame之后还能有这么大性能提升,估计需要仔细研究UE4渲染相关代码,个人不成熟的推测:以deferred shading为例,每个光源的在image space处理像素时,即使某个光源没有对当前像素产生明显影响,但是对应的计算过程仍然执行了,可能渲染层并没有因上层应用是游戏项目还是影视动画渲染而去做专门优化,而这个插件通过将灯光隐藏并禁用后,那么在处理各个像素光照信息时,这些光源的计算逻辑直接跳过了,所以可以大幅提升性能。

阴影优化如果使用了非静态的Directional Light(Stationary 或者 Movable),场景中有大量单位时,一定要开启Dynamic Shadow Distance(默认为0,表示关闭)。

测试用例: 500 个 Actor 同屏,摄像机高度4000,Stationary类型的Directional Light 的属性Dynamic Shadow Distance StationaryLight的值要大于摄像机到Actor的直线距离(注意:是到每个Actor的直线距离,所以值尽量要设置的大一些,比5000),否则帧率从200 fps 下降到 100 fps。

Dynamic Shadow Distance开启后能提升性能的原因:

Dynamic Shadow Distance 表示在多少距离内使用动态阴影,超过这个距离之外Fade成静态阴影,而Fade成静态阴影后就可以提升性能。

逻辑控制Cast Shadow

虽然灯光提供了属性DistanceField Shadow Distance来控制阴影根据摄像机距离投射,但是这种做法是一刀切。比如:假设性能瓶颈是大量怪物的阴影投射,远处山体和建筑的树木的阴影投射对性能影响很小,此时使用DistanceField Shadow Distance就会导致场景的表现效果大打折扣。推荐做法是,程序逻辑上控制:如果是怪物对象,只对离摄像机一定距离内的怪物开启阴影。

物体投射阴影的开关:

void UPrimitiveComponent::SetCastShadow(bool NewCastShadow)

材质优化材质类型的性能,从快到慢:Opaque -> Masked -> Translucent。

若场景中有大量单位,比如500个,那么这些单位一定要做材质LOD,并尽可能多的去掉半透明材质(比如在最后两级直接去掉半透明效果),否则性能消耗呈指数级增长。

如果GPUVisualizer的BasePass耗时较高,那么很大一部分原因是材质复杂度过高。

Decal消耗和像素数量有关,程序功能绝对不要乱用贴花,美术铺场景除外。比如程序想用贴花做一个范围标记,如果当标记范围很大时绝对不要用贴花,可以改成划线或者不通透贴图。如果场景需要大量使用贴花,根据视距动态创建和销毁贴花,仅仅SetVisibility是不够的,隐藏后还是会有巨大的开销(不过也可能是编辑器在地形编辑这块有bug,因为UE4场景编辑器有很多bug,特别当升级引擎版本后,旧版本中创建的地形在新版本中可能出现各种莫名其妙的bug)。

场景中的材质种类要提前规划好,拼场景时只在规划好的材质中选择。如果同屏的材质种类较多,会增加draw call。特别是场景美术用网上素材东拼西凑,很容易导致材质种类数量急剧上涨。

植被优化地形编辑时,使用Instanced Static Meshes。Intancing会增加GPU的开销,但是可以显著降低CPU的开销。注意:实际应用中,Instancing并不能作为减少CPU draw call次数的主要途径,因为实际的游戏场景不可能全是instanced mesh,即使是满屏的植被,也并非一定要用instanced mesh。要减少draw call次数,需要减少材质种类,提高材质复用率。

当Instanced Mesh的数量较多时(比如百万级),一帧内执行RemoveInstance或者UpdateInstanceTransform数次,帧率会狂泻。

优化办法:操作Instanced Mesh之前,将UHierarchicalInstancedStaticMeshComponent::bAutoRebuildTreeOnInstanceChanges设置为false,然后执行你需要的各种Instanced Mesh操作,操作玩之后,然后将bAutoRebuildTreeOnInstanceChanges设置为true,然后执行BuildTreeIfOutdated(true, false);,这样可以显著减少因操作百万级Instanced Mesh而导致的性能损失。

如果植被材质消耗成为瓶颈时,宁可增加面数,也不要使用 Translucent 材质,Masked酌情使用。比如一根草的面片,其整个形状全部使用三角面拼出来,而不要用一个三角面再加 Mask 或者 Translucent 材质的方式。

为Instanced Mesh设置合适的Cull Distance。

物理与碰撞优化BoxComponent的 Generate Overlap Events 设置为false。如果不需要Overlap事件,那么就将该属性设置设置为false,默认为true。当BoxCompont达到一定量级时,开启Generate Overlap Events的性能消耗是关闭情况下的两倍。

如果不需要物理,将 Simulate Physics 设置为false。

如果不需要Hit事件,将 Simulation Generates Hit Events 设置为false。

如果场景中物体类型(WorldStatic、WorldDynamic、Pawn等)很多,且每种数量也很多,则Collision 的 Object Response 通道设置的越少越好,把可以设置为 Ignore 的通道都设置为 Ignore 。如果场景中的物体类型比较单一,即使这种类型的物体在场景中有数百个,Object Response 即使都设置为Block 或者 Overlap,对性能也没有影响。

如果是大型RTS游戏,场景有海量单位时(比如星际2中大规模的虫族小狗),能不用UE4的 Collision 就不要用 Collision,否则帧数狂泻。

建议自己实现一个简易的自定义Collision,比如球形Collision,然后计算该 Collision 与单位之间的直线距离,来判断是否是否发生了碰撞,并且降低检测间隔,比如 0.1秒一次。用此种方式,如果单位数量较多时,还需要自己写一个类似Distance Filed的八叉树来缓存单位列表,以降低计算单位间距时遍历单位列表的循环次数。

动画优化打开角色蓝图 -》 MeshComponent -》 Detail 面板中的 Optimization 类别下 -》 勾选 Enable Update Rate Optimizations。

只对渲染的 SkinnedMesh执行 Tick 和 RefreshBoneTransforms

USkinnedMeshComponent::MeshComponentUpdateFlag = OnlyTickPoseWhenRendered;

默认是AlwaysTickPoseAndRefreshBones,表示不管是否被渲染(在可见区域内),都执行 Tick 和 RefreshBoneTransforms。

旧版本中MeshComponentUpdateFlag叫做SkinnedMeshUpdateFlag。

注意:如果关闭动画Tick,和Tick相关的逻辑就会失效,比如Transform (Modify) Bone。

动画蓝图的逻辑尽量直接访问成员变量,引擎默认开启了优化选项:动画蓝图中的成员变量在编译时会被复制到Native Code中,从而避免在运行时进入蓝图虚拟机(Blueprint Virtual Machine)执行蓝图代码,因为蓝图VM运行效率低。

默认会被编译优化的参数类型包括:

member variables;

negated boolean member variables;

members of a nested structure;

具体说明见官方文档:

Animation Optimization

https://docs.unrealengine.com/en-us/Engine/Animation/Optimization

Animation Fast Path Optimization

https://docs.unrealengine.com/en-us/Engine/Animation/Optimization/FastPath

UI优化能用HUD解决的就不要用UMG,等到需要显示时才创建Widget对象,不显示时则销毁,UMG对象较多时性能消耗巨大。

比如场景内有一千个单位,每个单位上都创建有WidgetComponent,即使这些WidgetComponent没有显示任何东西,也会产生巨大的GPU开销。

不能使用UMG来修改鼠标光标,因为UMG来制作响应速度较高的显示逻辑时,会有肉眼可见的明显延迟(由此可见UMG的性能消耗有多高),可以使用Hardware Cursors来代替UMG制作光标。

位移优化海量Pawn(比如500个)单位移动,如果是在 Tick 中使用 AddMovementInput 移动,帧率直接下降一半(比如从90帧下降到40多帧)。对于无法移动的单位,最好停止执行 AddMovementInput() ,以提升性能。

特效优化尽量不要使用 Volume domain,使用后会显著增加GPU开销。可以通过 profilegpu 检测 Volume 开销。

AI优化如果角色不需要 Controller ,就不要给它 Spawn Controller。如果一个角色长时间停止,则先给他Unpossesed() ,等到可移动时再PossessedBy()。

测试:500个角色,AI Controller Class 设置为:null、 AIController、PlayerController 的帧数分别为 120 fps、 100 fps、75 fps。

Dedicated Server优化服务端cook时剥离动画数据

Project Settings -> Engine -> Animation -> 勾选 Strip Animation Data on Dedicated Server.

如果在动画中添加了触发修改数据的 Notify Event,勾选此选项会有问题。请确保动画中挂载的 Notify 只是表现相关,不涉及游戏逻辑。

Server模式下禁用角色物理模拟

FBodyInstance->bSimulatePhysics 设置为false。默认为false。

SkeletalMeshComponent::bEnablePhysicsOnDedicatedServer 设置为 false , 默认为 true 。但这样会导致物理验算以客户端为准,有被外挂hack的风险。bEnablePhysicsOnDedicatedServer 在 run-time 修改不生效。

Server模式下禁用 Collision

UPrimitiveComponent->bGenerateOverlapEvents 设置为false,角色蓝图中的 CollisionComponent 默认为true。

Server模式下Detach角色身上所有的装饰性组件

AnimInstance的Root Motion Mode不要修改为Root Motion from Everyting,尽量使用默认值Root Motion from Montage Only,以减少服务器的动画同步计算量。

4.20提供了针对Dedicated Server优化的新特性:Replication Graph,可以初略地理解为针对网络通信的LOD(不过Replication Graph提供了不止网络层面的LOD,更多特性见官方文档)。没有这特特性之前,调用Multicast函数,几公里外的Actor也会触发Multicast,而实际上这种Actor可能不需要即时更新数据或者等到出现在视距内时再手动ForceNetUpdate()。有了Replication Graph之后,这种手动优化方式可以交给引擎自己管理。

其他参考

Performance and Profiling

CPU Profiling

GPU Profiling

Unreal Engine 4 Optimization Tutorial, Part 1-4

Optimizing and Profiling Games with Unreal Engine 4

Dynamic Lighting Portal System (Performance Booster)

Performance Optimization: Shadows Triggering Zones

通过优化在UE4中实现良好性能和高质量视觉效果

Unreal Insights(New feature in v4.23)

ue4渲染速度太慢_[UE4]性能优化指南(程序向)相关推荐

  1. ue4渲染速度太慢_推介飞向月球纪录片基于Unreal实时渲染引擎的三维流程化制作...

    作者:中央电视台 葛小丁 2019年1月3日上午10点26分,"嫦娥四号"探测器成功着陆在月球背面东经177.6度.南纬45.5度附近的预选着陆区,并通过"鹊桥" ...

  2. ue4渲染速度太慢_技术汇丨如何在UE4中实现最佳性能和高质量视觉效果

    合并网格 如之前在线框可视化解释中提到的,减少三角形和顶点的数量永远都是提高性能的方法,但是很多时候,一个单独网格比多个网格刻画集合图形的性能要好得多(一个有1000个顶点的网格可能比10个有100个 ...

  3. ue4渲染速度太慢_UE4 渲染性能设置

    LightingAllow Static Lighting : 是否开启静态光照, 开启后将生成 lightmap, shadow map之类的可在静态光照下使用的贴图,否则仅使用动态光照, 修改此项 ...

  4. [UE4]性能优化指南(程序向)

    零散记录 GPUProfile来统计性能消耗的时候,在editor模式下不是很准,因为编辑器的消耗也算进去了,如果要用,最好以Game模式来查看. UE4不支持640X480的分辨率,如果在这个分辨率 ...

  5. smb服务器速度测试_SMB 文件服务器的性能优化

    SMB 文件服务器的性能优化Performance tuning for SMB file servers 4/14/2017 本文内容 SMB 配置注意事项SMB configuration con ...

  6. 移动H5前端性能优化指南[转]

    移动H5前端性能优化指南 米随随2015.01.23 移动H5前端性能优化指南 概述 1. PC优化手段在Mobile侧同样适用 2. 在Mobile侧我们提出三秒种渲染完成首屏指标 3. 基于第二点 ...

  7. Spark性能优化指南:高级篇

    前言 继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化指南>的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加棘手的性能问 ...

  8. Spark性能优化指南——高级篇

    继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化指南>的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加棘手的性能问题. ...

  9. 移动HTML5前端性能优化指南

     http://www.cocoachina.com/webapp/20150126/11020.html (点击看大图) 移动H5前端性能优化指南[托尼托尼研究所] 概述 1. PC优化手段在M ...

最新文章

  1. JavaScript语言基础11
  2. ad19pcb设置恢复默认_条码打印机-斑马产品常用恢复出厂设置
  3. 与崇洋媚外的程序员的辩论
  4. Ext Designer Preview生成代码在html上显示步骤
  5. JSON 序列化 与 反序列化
  6. Oracle分析函数、多维函数和Model函数简要说明,主要针对BI报表统计
  7. .net解析传过来的xml_隧桥管廊BIM+GIS运维管理系统方案解析
  8. NPOI 设置合并后的单元格的边框的解决方法
  9. Java毕设项目宠物管理系统计算机(附源码+系统+数据库+LW)
  10. linux下查询utp命令,Linux后台下载工具(器)transmission 使用详解
  11. HTML5系列代码:信纸效果
  12. 单核工作法图解:事多到事少,拖延变高效
  13. 谈中国分布式数据库商业之路:OSM与DB-Inside
  14. DBeaver——设置字体大小
  15. MaxCompute SQL引用第三方Base64JAR实现编解码
  16. Windows server 2016 Windows 10 离线下载与离线安装补丁教程 支持批量安装(其他win系统类似)
  17. js MessageBox 类 无插件,支持弹出层(原页面div 或者 div代码),消息框(alert confirm)
  18. java后端判断图片尺寸(GB,MB,KB形式),图片色彩(黑白照或彩色照片),图片构图(横图竖图方图)
  19. 阿里云服务器在哪?阿里云服务器最新可选地域分享
  20. Scrapy + Selenium 实现模拟登录,获取页面动态加载数据

热门文章

  1. 华为云上部署Seafile私人网盘
  2. 2022年度软件质量保障行业调查报告
  3. 使用Markdown追溯产品文档历史版本
  4. 武汉交管网 “机动车车主基础信息采集”
  5. PMP知识点总结—ADM与PDM的区别
  6. 基础设施建设取得新进展,区块链产业化提速 | 产业区块链发展周报
  7. 七牛云对象存储设置自己的域名访问(阿里云的域名)
  8. MySQL 进阶 视图 -- 视图介绍、视图CRUD语法、检查选项(CASCADED、LOCAL)、视图的更新、视图作用、视图案例
  9. 大数据面试3分钟自我介绍_大数据面试自我介绍技巧
  10. Keras:Unet网络实现多类语义分割方式