--- title: UE5优化方法与实践笔记 date: 2022-09-26 10:06:37 excerpt: tags: rating: ⭐⭐ --- ## 前言 - 视频推荐: - https://www.youtube.com/watch?v=ZRaeiVAM4LI - 其他: - https://zhuanlan.zhihu.com/p/629225258 - Tomlooman的优化建议:https://www.tomlooman.com/wp-content/uploads/2022/11/Unreal-Engine-Game-Optimization-on-a-Budget.pdf GPU Visualizer工具显示命令: **ProfileGPU** CPU优化方法:https://www.unrealengine.com/en-US/blog/how-to-improve-game-thread-cpu-performance ### Sample Workflow 1. Run `Stat unit` - shows the render thread is taking 50 ms. 2. Then run `stat scenerendering` - shows that 25 ms is in the RenderViewFamily - leaving us with 25 ms that the render commands are taking up 3. Finally, run `stat sceneupdate` - we see that there is 25 ms in AddLight RT - we see that it is being called 10 times a frame 4. We then need to go look at who is calling AddLight via a break point. And see why adding a specific light or lights is so slow. Usually it is the case that a specific light being added in a way that is doing more work than actually needs to be done. (e.g. attaching / reattaching it) # 优化前需做 - r.vsync 0 - t.maxfps 0 - SmoothFrameRate=False (Project Settings) - Lighting Built & MapCheck Errors fixed. - Packaged Game build - 使用Standalone进行优化。 ## 优化笔记 r.Lumen.DiffuseIndirect.MeshSDF.RadiusThreshold 让物体包围球的半径大于上述两个决定的数值的时候,才参与mesh sdf的软追踪。 某些情况下,创建移除 WPO/PDO 的材质 LOD 可能不切实际,但这些转换的最终效果在远处很小。用于`r.Shadow.Virtual.Cache.MaxMaterialPositionInvalidationRange`设置一个距离(以厘米为单位),超过该距离将忽略这些材质的缓存失效。 为了在这些情况下更好地优化,可以使用启用可选的**单独静态缓存**`r.Shadow.Virtual.Cache.StaticSeparate 1`模式。此模式将物理页面池的大小加倍,以便可以将给定页面中的静态几何与动态几何分开缓存。即使动态几何移动了,也不需要重新绘制静态几何。 ### Nanite r.Nanite.AllowWPODistanceDisable ### 非纳米变形和树叶 可以使用骨骼动画变形的几何体,或使用世界位置偏移或像素深度偏移的材质总是使缓存页面每帧无效。根据定义,这些案例也必须是非 Nanite——这更昂贵——因此确保谨慎使用这些功能并控制边界是极其重要的。 在某些情况下,例如草地,有时是树叶,仅使用[接触阴影](https://docs.unrealengine.com/5.0/en-US/contact-shadows-in-unreal-engine)就足以替代高分辨率阴影贴图。在前景中需要高细节阴影的情况下,请考虑以下内容以帮助降低性能成本: - 非 Nanite 对象仍然遵守常规阴影 CPU 剔除设置,例如`r.Shadow.RadiusThreshold`. 使用这些来帮助控制将这些对象渲染到虚拟阴影贴图中的成本。 - 在有很多树叶的场景中,强烈建议使用 禁用粗糙页面中的非 Nanite 对象`r.Shadow.Virtual.NonNanite.IncludeInCoarsePages 0`。或者,考虑在不需要时 [完全禁用粗糙页面。](https://docs.unrealengine.com/5.0/en-US/virtual-shadow-maps-in-unreal-engine#coarsepages) - 在效果不再明显的距离使用网格 LOD 切换到不使用 WPO/PDO 的材料。在某些情况下,可以关闭远处这些对象的动态阴影投射,并完全依赖屏幕空间接触阴影。 对于平行光,还有其他可用选项: - 距离场阴影接管非 Nanite 几何体,超出由光的级联阴影贴图部分设置的**动态阴影距离可移动光距离。**为远处的非 Nanite 切换到距离场阴影可以显着提高性能,因为该几何体不具有 Nanite 提供的细粒度 LOD 缩放。 - 在某些情况下,创建移除 WPO/PDO 的材质 LOD 可能不切实际,但这些转换的最终效果在远处很小。用于`r.Shadow.Virtual.Cache.MaxMaterialPositionInvalidationRange`设置一个距离(以厘米为单位),超过该距离将忽略这些材质的缓存失效。 如果运动很明显,这可能会导致阴影“模糊”,并且对象会错误地自我形成阴影,但通常这些伪影是性能和便利性的合理折衷。 ### 普通植被 普通植被最快,最有效的优化方式是做好LOD,减少culling distance.除此之外,还有两个因素对性能也有一定的影响。 - foliage actor的范围 foliage actor的默认tile的大小是256,如果一个tile下有大量的植被,而且植被密度非常浓密的时候,这里不仅会引起分区流送引起cluster tree构建的卡顿,也会导致gpu下prepass和basspass消耗过高,因为默认的剔除盒子太大,导致prepass和basspass存在大量的vs的overdraw. - cluster tree遮挡剔除盒子大小 cluste tree的剔除盒大小,决定了这一块instance是否绘制,过大的盒子,会引起prepass和basspass的vs阶段的overdraw,过小的盒子,导致存在大量的遮挡剔除查询导致render线程耗时过高,而且也会产生过多的drawcall。引擎对于cluster tree的控制参数都是全局的,有一些component适用,也一些则不合适。过密的component须要提高盒子的粒度,过于稀疏而且面数不高的,可以减少盒子数。因为,如果植被特别影响性能的时候,可以修改引擎支持让这些参数跟着component走。引起cluster tree盒子的因素有点多,这里主要聊三个。 foliage.MaxOcclusionQueriesPerComponent 控制每个component的最多盒子数 foliage.MinOcclusionQueriesPerComponent 控制每个component的最少盒子数 foliage.MinInstancesPerOcclusionQuery 控制每个盒子最小包含的实例数 如果这个盒子粒度控制好,在植被比较多的情况下,可以在prepass和basspass省下2MS的预算。 ### 贴图优化 具体参看:Managing the Texture Streaming Pool:https://www.youtube.com/watch?v=uk3W8Zhahdg 大致步骤: - 使用Tools - Audit - Statistics查看贴图占用显存以及场景中的使用数量。 - 通过ViewMode - OptimizationViewModes - RequiredTextureResolution 查看贴图在场景中所需要的占用比例是否合适。 - 使用批量编辑功能修改Texture资产的MaximumTextureSize到指定Mipmap层级的分辨率即可。 另一个种方式就是使用SVT。 ## 游戏的优化指标 目标性能:30帧 约30ms 2000-3000是合理drawcall次数;5000较高;10000有问题 ### 优化建议 1. 远景或者不太容易见到的灯光不产生阴影 2. Spotlight不要超大开角,可以降低阴影分辨率,衰减半径不要设置过大,只需照亮需要照亮的主题即可,如果不投射阴影可以改成点光源。 3. 灯光需要减少级联阴影的使用量,在远景处尽可能得使用距离场阴影 1. 方向光:降低DynamicShadowDistanceMoveableLight,Num Dynamic Shadow Cascades的值。适当调整DistanceFieldShadowDistance与DistanceFieldTraceDistance。 2. 其他光:降低**Max Draw Distance**,减少渲染范围;控制**Attenuation Radius**、**Cone Angle**减少叠加。具体可以使用**ViewModel - Optimization ViewModes - Light Complexity**来进行检查。 3. 其他光:降低ShadowResolutionScale;并且调整亮度,让玩家看不出阴影质量较低。 4. 对于**非Nanite物体**的阴影,可以使用**r.Shadow.RadiusThreshold**来减少投射阴影的物体数量。 5. VSM 1. 局部光:16k,8级Mipmap 2. 方向光:16k, 17级Clipmap 3. 纹理池上限:`r.Shadow.Virtual.MaxPhysicalPages (4096)` 4. Lod精度偏移 1. `r.Shadow.Virtual.ResolutionBiasDirectional` 2. `r.Shadow.Virtual.ResolutionBiasLocal` 5. 减少SMRT的采样次数来提高软阴影的性能。 4. Lumen 1. 距离场的设置![[Lumen_StaticMeshDistanceFieldSettings.png|1000]] 5. Nanite 1. UE5.1针对树等植被,采用了直接的建模式树叶而非之前的Mased+卡片的方式实现,此时再配合StaticMesh中NaniteSettings的**Preserve Area**。拉远了树木上的树叶就不会消失了。 1. 2. 2. UE5.1支持了WorldPositionOffset,但这个效果在远距离下并不明显,需要根据距离优化掉。可以通过**View Mode - Optimization View Mode - Evaluate World Position Offset**来查看。 6. 控制RayTracing渲染功能的距离与范围 1. 按角度与距离剔除 1. r.Raytracing.Culling 1 2. r.Raytracing.Culling.Radius 10000 (100米) 3. r.Raytracing.Culling.Radius 1 (5度) 2. 设置光追组 1. StaticMeshComponent - RayTracing - Advanced - Raytracing Group Id /Culling Priority 7. 针对粒子特效,可以调节Cut Off的裁剪系数,Spawn Time,Spawn Rate等等可以在保证效果的同时来降低粒子数量的参数 1. https://www.youtube.com/watch?v=_T-BTiMF7XA 2. https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/RenderModules/ 8. 尽可能使用贴花 9. 模型优化 1. 给模型生成LOD以及HLOD 1. Level Of Detail Coloration->Mesh LODs(可以**用红绿蓝三种颜色来**检验不同屏幕尺寸的LOD变化) 2. 对于远处会闪烁的模型,需要关闭LOD的`自动计算LOD距离`,并且手动制作LOD。 2. 模型转换为Nanite后,可以使用Nanite Tools来检查Nanite转换是否正确 3. 如果是**大量OverDraw Nanite模型**,可以使用**UE内置建模工具**的**Merge功能**将模型进行合并。 10. 使用剔除功能减少渲染的图元数 1. 使用`Stat InitViews`检查当前渲染图元数,以及之后优化完之后的图元数。**View Visibility**、**Occlusion Cull**为剔除消耗,**Processed**、**Frustum Culled**、**Occluded**剔除前后图元变化。 2. 给模型的LOD选项中设置**MinDrawDistance、DesiredmaxDrawDistance、CurrentMaxDrawDistance让模型在较远处被剔除**,适合一些细小的装饰类模型。 3. 使用剔除用Volumn。 11. 材质、蓝图等等,如果可以创建实例就使用实例 12. 综合优化视频 1. Adjusting Your Content to Perform on Target Hardware https://www.youtube.com/watch?v=Ln8PCZfO18Y 13. 贴图优化 1. 调整贴图的LOD Bias 2. 使用rdTexTools 插件优化贴图 14. 使用MergeActor工具,将模型转化成Instance或者将细碎的模型组合成一个模型。 15. 调整材质:减少材质复杂度以及使用的材质指令量。EPIC给出的建议:300左右正常、**500+优化**、**1000+尽量减少**。 16. HLOD 估计适合组合拼装的房子 https://www.youtube.com/watch?v=WhcxGbKWdbI 1. 知乎介绍文章:https://zhuanlan.zhihu.com/p/77509062 2. HLOD需要在世界设置中的LODSystem中打开。 17. 场景模型剔除 推荐视频:https://www.youtube.com/watch?v=6WtE3CoFMXU 1. Show-Visualize-Advanced-CameraFrustums,可以查看摄像机范围外的物体与遮挡物体。 2. Volumn 1. CullDistanceVolumn: 根据对象距摄像机的距离及其尺寸,对对象进行剔除(即不绘制到屏幕上)。当对象小到可被视为不重要时,即可不绘制对象,从而优化场景。尺寸是按照边界框的最长边计算的,而剔除距离是根据与该尺寸最接近的距离计算的。 2. HierarchicalLODVolumn 3. MeshMergeCullingVolumn:与HLOD有关 4. PrecomputedVisibilityVolumn:这类体积会保存Actor的可视性,以了解它们在场景中的位置。应仅将这些体积放置在玩家可以到达的区域。(视频是把玩家可以到的地方直接放满了) 3. Debug方法 1. FreezeRendering:Foliage.Freeze、FX.FreezeGPUSimulation、FX.FreezeParticleSimulation 2. r.VisualizeOccludedPrimitives1 3. ToggleDebugCamera 18. UE5 OpenWorld WorldComposition Datalayer ,里面有附带大世界的HLOD 以及Nanite生成方法以及对应的CommanLet:https://www.youtube.com/watch?v=ZxJ5DG8Ytog # 场景 在蓝图中放置多个&多层StaticMeshComponent结构,在移动时会爆卡。可以在子Component中勾选***Use Attach Parent Bound***即可避免多层级的BoundingBox更新而导致卡顿。 ![[UE5 MergeActor使用笔记]] ### DLSS与动态分辨率 DLSS 在5.03上没有效果,动态分辨率不支持PC。 https://docs.unrealengine.com/5.0/en-US/dynamic-resolution-in-unreal-engine/ ### 蓝图的方法 ![900](https://docs.unrealengine.com/5.0/Images/designing-visuals-rendering-and-graphics/rendering-optimization/dynamic-resolution/DynamicResBlueprint.webp) ### c++的方法 ``` GEngine->GetDynamicResolutionStatus()->SetEnabled(true); ``` 将 _SetEnabled_ 设置为 **false** 可将其禁用。 >在实际启用或禁用动态分辨率时,游戏线程逻辑掌握最终程序控制权限,所以如果你是用蓝图在运行时启动它,这会优先于代码设置。要将游戏用户设置恢复到初始状态,请使用以下命令行: ``` GEngine->GameUserSettings->ApplyNonResolutionSettings(); ``` ### 命令行 你可以使用 **运算模式(Operation Mode)** 设置如何在游戏中覆盖和使用动态分辨率,设置在游戏中覆盖它和使用它的方式。为了控制这种模式,在项目所对应平台(Xbox One、PlayStation 4等)的平台配置描述(或设备描述)中,你可以使用下列控制台命令: ``` r.DynamicRes.OperationMode ``` 使用下列数值之一来设置运算模式如何针对项目的平台工作: - **1** 是根据游戏用户设置状态(在C++或蓝图中设置)启用动态分辨率。 - **2** 是无论游戏用户设置状态如何都启用动态分辨率。 启用动态分辨率后,下列控制台变量会设置屏幕百分比的最大值和最小值,以及在降低分辨率之前任何给定帧的最大预算。如果你不设置,这些变量都有默认值: | 控制台变量 | 默认值 | 描述 | | -------------------------------- | ------ | ------------------------------------------ | | r.DynamicRes.MinScreenPercentage | 50 | 设置要使用的最小屏幕百分比。 | | r.DynamicRes.MaxScreenPercentage | 100 | 设置用于分配渲染目标的最大主要屏幕百分比。 | | r.DynamicRes.FrameTimeBudget | 33.3 | 设置帧预算(以毫秒为单位)。 | 你可以使用Unreal Engine中的"设备描述(Device Profiles)"窗口设置和管理配置文件。可以通过"文件(File)"菜单选择 **编辑(Edit)> Developer Tools(开发者工具)> Device Profiles(设备描述)** 来访问此窗口。 ### 暂停和恢复动态分辨率 有时你可能需要为项目启用动态分辨率,但你又不想对主大厅之类的区域启用。动态分辨率可以随运作模式暂停和恢复。下列控制台变量可用于设置动态分辨率的运算模式: ``` r.DynamicRes.OperationMode ``` | 数值 | 描述 | | ---- | ------------------------------------------ | | 0 | 禁用(默认) | | 1 | 根据GameUserSettings中使用的设置启用。 | | 2 | 无论GameUserSettings中的设置如何都会启用。 | ## DLSS 与 FSR UE5使用DLSS时需要关闭TAA,并且调整[[ScreenPercentage与描边宽度问题解决]] ### DLSS - 下载地址:https://developer.nvidia.com/rtx/dlss/get-started#ue-version ### FSR - 使用方法与参数详解:https://zhuanlan.zhihu.com/p/437537928 - 下载地址:https://gpuopen.com/learn/ue-fsr2/ # 内存数据查看 - stat llm:查看**虚拟内存数据**。需要在启动方式里添加`-llm`才会有数据。 - MemoryInsight:需要在启动方式里添加`-trace=memory`,之后才能在UnrealInsight中查看。 # 材质优化 MIN/MAX DRAW DISTANCE 使用DistanceCullFade节点将过远的部分给Cull掉。 ![[Unreal-Engine-Game-Optimization-on-a-Budget_MINMAX DRAW DISTANCE.png]] # FREEZERENDERING 冻结渲染以此查看剔除情况。 - ‘FreezeRendering’ + ; (semi-colon) to fly with DebugCamera - Verify occlusion is working as expected - ‘pause’ (Freeze Game Thread) # LIGHT CULLING (Stationary & Movable) - Automatic ScreenSize culling not strict enough - MinScreenRadiusForLights (0.03) - Cull earlier case-by-case - MaxDrawDistance - MaxDistanceFadeRange - Profiling - Show > LightComplexity (Alt+7) - Show > StationaryLightOverlap - ToggleLight # LEVEL STREAMING 关卡流调试方法 - Streaming Volumes vs. Manual Load/Unload - Camera Location based (caution: third person view and cinematic shots) - Cannot combine both on a specific sublevel, can mix within the game - Profiling - stat levels - Loadtimes.dumpreport (+ loadtimes.reset) - Unreal Insight - UnrealInsight相关标签:Look for level load & “GC” bookmarks - UnrealInsight相关追踪内容:loadtime,file categories # Animation ## ANIMATION: FAST PATH - Allow ‘Fast Path’ by moving Computations out of AnimGraph (into EventGraph) - Use WarnAboutBlueprintUsage to get warnings in AnimGraph - Profiling - stat anim ## ANIMATION: QUICK WINS - **Update Rate Optimization (URO) for distant SkelMeshes**:根据距离调整骨骼物体的更新频率,该选项位于SkeletalMeshComponent。 - VisibilityBasedAnimTickOption (DefaultEngine.ini) - OnlyTickPoseWhenRendered - AlwaysTickPoseAndRefreshBones - … - More Bools! - bRenderAsStatic :UE5.2不存在该选项。 - bPauseAnims:该选项位于SkeletalMeshComponent。 - bNoSkeletonUpdate:该选项位于SkeletalMeshComponent。