【游戏开发】UE4-性能优化指南!

2021-05-18
7146
0

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

 

 

零散记录

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

 

2.UE4不支持640X480的分辨率,如果在这个分辨率下运行程序,会导致程序崩溃。

 

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


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

 

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

 

代码算法优化(仅限UE4 API相关)

1.清空TArray时,如果该TArray对象还会继续使用,使用Reset()代替Empty(),因为前者不会销毁内存空间。

 

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

 

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

 

视距裁剪(剔除)

1.开启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

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

 

阴影优化

1.如果使用了非静态的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成静态阴影后就可以提升性能。

 

2.逻辑控制Cast Shadow


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


物体投射阴影的开关:


void UPrimitiveComponent::SetCastShadow(bool NewCastShadow)

 

材质优化

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

 

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

 

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

 

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

 

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

 

物理与碰撞优化

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

 

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

 

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

 

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

 

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


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

 

位移优化

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

 

特效优化

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

 

AI优化

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


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

 

 

转载声明:本文来源于网络,不作任何商业用途。

免责声明:本文内部分内容来自网络,所涉绘画作品及文字版权与著作权归原作者,若有侵权或异议请联系我们处理。
收藏

全部评论

您还没登录

暂无留言,赶紧抢占沙发
绘学霸是国内专业的CG数字艺术设计线上线下学习平台,在绘学霸有2D绘画、3D模型、影视后期、动画、特效等数字艺术培训课程,也有学习资源下载,还有行业社区交流。学习、交流,来绘学霸就对了。
绘学霸iOS端二维码

IOS下载

绘学霸安卓端二维码

安卓下载

绘学霸微信小程序二维码

小程序

版权声明
本网站所有产品设计、功能及展示形式,均已受版权或产权保护,任何公司及个人不得以任何方式复制部分或全部,违者将依法追究责任,特此声明。
热线电话
17688437870
咨询时间:9:00~21:00
在线客服
联系网站客服
客服微信:17688437870
公司地址
中国·广州
广州市海珠区晓港中马路130号之19
绘学霸客户端(权限暂无,用于CG资源与教程交流分享)
开发者:广州王氏软件科技有限公司 | 应用版本:Android:6.0,IOS:5.1 | App隐私政策> | 应用权限 | 更新时间:2020.1.6