关于粒子特效的一些基础知识,可以参考 【UE4】特效之 Particle System 详解(一)—— 综述
一、特效池是干嘛的
举个粒子解释一下池子:
比如你是弓箭手,你会射箭,你会从地上(内存)捡树枝打造弓箭(NewObject)。
- 如果没有箭袋
那每次想射箭,都需要从地上捡树枝打造弓箭,这个过程想想就很麻烦,所以你的效率很低 - 如果背上背了箭袋
那么你可以在从地上捡树枝打造弓箭,并射出去之后,把弓箭捡回来,插到箭袋里,下次想射箭,如果箭袋里有弓箭,那直接拿出来射就行,不需要重新打造
以上是个人理解,有问题可以讨论~
值得注意的是:
- 能这样做的基础是,每次射出去的弓箭,最后都会捡回来,除非箭袋都没了(即弓箭的生命应该完全由箭袋管理),不捡回来的箭袋就没有意义了,还得背着。。
- 箭袋是有大小的,放了 100 支箭之后,就放不下第 101 支了(至于为什么会有第 101 支箭,是因为不是每次射箭之后都有时间把那支箭拿回来,可能一次要放五支箭出去,然后又射了三支,过一会再把这八支一起拿回来,所以在这个过程中,地上的箭和箭袋中的箭加起来,可能超过了箭袋的容量,那么,捡的时候捡满了就不捡了)
- 从箭袋中拿箭,把箭放回箭袋的操作都不麻烦,至少一定要比从地上拣树枝子打造弓箭要容易,不然每次弄新的不就好了。
1.1 使用特效池的目的
ParticleSystem(俗称粒子特效)的释放最终调用的都是 CreateParticleSystem
函数,如下所示:
UParticleSystemComponent* CreateParticleSystem(
UParticleSystem* EmitterTemplate,
UWorld* World, AActor* Actor,
bool bAutoDestroy,
EPSCPoolMethod PoolingMethod)
{
//Defaulting to creating systems from a pool. Can be disabled via fx.ParticleSystemPool.Enable 0
UParticleSystemComponent* PSC = nullptr;
if (FApp::CanEverRender() && World && !World->IsNetMode(NM_DedicatedServer))
{
if (PoolingMethod != EPSCPoolMethod::None)
{
//If system is set to auto destroy the we should be safe to automatically allocate from a the world pool.
PSC = World->GetPSCPool().CreateWorldParticleSystem(EmitterTemplate, World, PoolingMethod);
}
else
{
PSC = NewObject<UParticleSystemComponent>((Actor ? Actor : (UObject*)World));
/// PSC->xxx = xx 等一些初始化操作 blablabla...
}
}
return PSC;
}
核心逻辑就是,如果 PoolMethod 不是 None
,则从池子中取;如果是 None
,则会 NewObject
,即每次释放一个特效,都会创建新的。
NiagaraSystem(俗称奶瓜特效),也是一样,接口是 CreateNiagaraSystem
,也是每次 NewObject。
Note: 值得注意的是,两种特效都进行了
World && !World->IsNetMode(NM_DedicatedServer)
的判断,即特效在服务器上是都不会创建的,所以不需要关心服务器上的特效会NewObject
,但是如果是 Actor 上挂载的
ParticleSystemComponent(不管是从代码,还是从蓝图资源),是会在服务器创建 Component 的,这点需要注意。
由于 NewObject 会进行一系列操作,所以对 CPU(GameThread)肯定是有消耗的(虽然一个可能不多,但是架不住数量多啊),所以如果能够利用池子进行缓存,每次不新创建,而是从