IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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才能使用对象池。

  • AutoRelease:在lifetime到时间后自动放回池子里。
  • ManualRelease:意味着后续需要你自己手动调用ReleaseToPool方法才能把特效放回池子里。

蓝图里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源码。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 13:05:24  更:2022-10-17 13:06:28 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码