| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 深谈UE4粒子系统对象池的惊人大坑 -> 正文阅读 |
|
[游戏开发]深谈UE4粒子系统对象池的惊人大坑 |
抓手标题起得很唬人,但一点不唬人。 作者在这里告诫大家,不要使用Cascade的对象池,会有bug,并且不起作用! 建议大家都转成使用Niagara,Niagara的对象池功能齐全,并且没什么bug。 后面会具体说明原因。 同时本文会告诉大家大家具体的使用方法,以及什么情况下需要使用对象池。 本文将基于UE4.26.2的源码进行分析研究。 UE4粒子对象池的大坑Cascade和Niagara的对象池代码原理几乎一致,但是感觉是两个人写的。(而且是负责Niagara的同学复制Cascade的对象池代码来改改) 所以Niagara有一定的优化,Cascade有坑。 具体的坑,有五个: 1、Cascade的对象池没有初始化多少个实例的功能,虽然Cascade的UI上看起来可以设置,但却没有实际功能!而Niagara是有该功能的。 原因是ParticleSystem类和NiagaraSystem类都继承了父类UFXSystemAsset,都有??? uint32 PoolPrimeSize = 0; 这个变量。但ParticleSystem却没有实现相应的功能。反而NiagaraSystem在Postload方法里调用了 PostLoadPrimePools方法去做这件事。 2、从Cascade的对象池里取出的实例会重新Register Component。而Niagara则默认不重复register。这样导致Cascade粒子从对象池取出来,照样会浪费CPU的消耗,而且消耗还不低。 在我的机子11代i7 CPU上,regiseter一次Component居然需要花费2ms左右,怎么可能不卡? ?而Niagara的优化: ?Niagara还注释了为了避免Register/Unregister Component的消耗: 3、即便从Cascade的对象池取出的实例,attach到某个component上仍然调用的是SetupAttachment方法,而不是AttachToCompoent方法。但SetupComponent是构造函数里调用才生效的,所以从Cascade对象池取出的无法正确attach到component上! 4、调用SpawnEmitterAtLocation方法去Spawn粒子,从Cascade的对象池取出的实例无法正确设置它的transform!因为它调用的是SetRelativeLocation_Direct和SetRelativeRotation_Direct,该方法只能在初始化的时候调用才能起效,因此Niagara改成了SetWorldLocationAndRotation,该方法会后续用tick update的办法去更新位置和rotation。 5、Niagara有个小坑,就是AnimNotify_PlayNiagaraEffect是不开启对象池的,如果不想改引擎代码,就只能重载该方法才能使用了。同理,Cascade的AnimNotify_PlayParticleEffect也是。 Cascade的对象池源码在: UGameplayStatics.cpp和WorldPSCPool.cpp Niagara的对象池源码在: NiagaraFunctionLibrary.cpp和NiagaracomponentPool.cpp 如果细看的话,这两份代码不能说是毫无关系,只能说逻辑几乎一模一样。 如果想用Cascade的对象池,建议按照Niagara的做法把Cascade的bug给修了。具体查看上面的每个对比的点。 具体使用方法(仅介绍Niagara)初始化对象池: 打开NiagaraSystem,选择System,然后在Selection面板的System Properties?,Performance里的Pool Prime Size,填入大于0的数字: 但Pool Prime Size大于Max Pool Size,它也只会按Max Pool Size的数量来初始化,所以可以适当调整Max Pool Size数量大于或等于Pool Prime Size数量。 调用代码去Spawn时: UNiagaraFunctionLibrary::SpawnSystemAttached或SpawnSystemAtLocation方法,在参数里传入ENCPoolMethod::AutoRelease或者ManualRelease才能使用对象池。
蓝图里Spawn: ?Pooling Method选择AutoRelease或者ManualRelease。 为什么需要使用对象池? ? ? ? 因为UE的粒子在Spawn的时候,ActorComponent需要注册Component,这个时候就会对CPU产生比较大的消耗。 ????????而使用对象池的优化原理就是,先初始化一定数量的实例在池子里,然后需要的时候再去池子里取,然后在激活使用。 ????????什么时候需要使用对象池呢?就是同一种粒子特效需要高频播放的时候,或者同时大量播放的时候,那么对象池是对于CPU消耗来说,是个必备良药。代价只是多占了那么点内存嘛,初始化加载时间会多一点点嘛(只要数量不会太夸张,用到成千上万的数量)。 总结:????????对于一个这么大的引擎来说,有这样的bug的确是让人意料之外,但UE也希望大家都使用Niagara,Cascade也在被慢慢遗弃,截止到4.27,Cascade对象池的问题依然存在。而UE5则默认是关闭Cascade的。 ????????所以本文作者在这里也呼吁大家都直接转为使用Niagara,虽然4.26的Niagara确实还有一些不好用的bug,但如果熟悉了,也是能避免的。并且Niagara更自由了。如果完全不使用对象池,则继续使用Cascade粒子是没问题的。 参考:Unreal引擎4.26.2源码。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/17 6:06:02- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |