本文使用 UE4.26 版本,利用 ActionRPG 示例项目,对 UE 中的粒子特效 (Particle System) 进行学习,总结(虽然 UE5 已经不太打算用这个了,而是使用 Niagara,但是了解还是很有必要的),主要包括:
- 特效编辑器 Cascade 与 Particle System
- 特效相关优化
- 特效相关问题记录
Restart Level
空格(Space),可以按上边的 Restart Level 按钮一样,重新从 0 开始播这整个特效
切换发射器设置和整个特效设置
点击一个发射器(Emitter),Details 中会显示发射器的设置,点击发射器中的 Module,Details 中会显示 Module 的设置;如果想切换成整个特效的设置,点击最右侧的黑色区域即可(这也就是为什么不管怎么加发射器,最右边都会留有黑色区域)。
重置摄像机
在预览窗口鼠标右键、左键按住,WASD移动摄像机的操作和正常的编辑器游戏窗口中一样,但是有时候转着转着特效就不知道去哪儿了,这时候,点一下 F
按键即可。
背景颜色和 Bounds
上方的 Background Color
选项可以修改预览窗口的背景颜色,为了更好的观察特效;Bounds 按钮可以显示特效的 Bounds,用于查看是否会有问题,或者 Bounds 过大导致效率降低等。
在 UE 中编辑 ParticleSystem 的编辑器叫 Cascade(双击打开一个 Particle System 资源即可),界面如下图所示:
右侧中间的这部分最重要,是 Emitters,即粒子发射器。
其中每一个竖着的方块每一个 Emitter,Emitter 有四种类型(像下图就是一个 Mesh 类型 Emitter):
其中:
每一个 Emitter 里的每一横条,是一个 Module(如下图就是一个 Required Module):
每个 Module 里的 Details 里,是对于这个 Module 或者说,这个粒子特效的描述(如下图就是 Required Module 的一部分 Detail)
想到再写
在代码里,创建出的是 UParticleSystemComponent 类型的特效,如:
UParticleSystemComponent* PSC = UGameplayStatics::SpawnEmitterAtLocation(
Target->GetWorld(),
PSTemplate,
StartLocation,
Rotator);
其中所有的粒子是 Emitter Instances,即 1.1 中的 Emitters:
TArray<FParticleEmitterInstance*>& EmitterInstances = PSC->EmitterInstances;
这是个数组,其中每一个就是 1.1 中的每一个 Emitter(FParticleEmitterInstance 类型):
for (FParticleEmitterInstance* const EmitterInstance : EmitterInstances)
{
}
每个 Emitter 可以转成对应的类型,如 Beam 类型的可以直接转
FParticleBeam2EmitterInstance* const Beam = StaticCast<FParticleBeam2EmitterInstance*>(EmitterInstance);
if (Beam && Beam->BeamTypeData)
{
Beam->BeamTypeData->Speed = TraceSpeed;
}
对于 Emitter 中的每一个 Module,通过如下方式获取:
EmitterInstance ->CurrentLODLevel->Modules
想要获取特定类型的 Module,可以直接转,如 Lifetime 这个 Module,就是 UParticleModuleLifetime 类型的(详见 \UnrealEngine\Engine\Source\Runtime\Engine\Classes\Particles 下的文件夹和 .h)
其中 RequiredModule 比较特殊,单独存的(详见 UParticleLODLevel 类声明),即 每个发射器都有一个Required模块(官方翻译就是:默认必需的模块):
class UParticleLODLevel : public UObject
{
GENERATED_UCLASS_BODY()
/** The required module for this LOD level */
UPROPERTY(instanced)
class UParticleModuleRequired* RequiredModule;
/** An array of particle modules that contain the adjusted data for the LOD level */
UPROPERTY(instanced)
TArray<class UParticleModule*> Modules;
}
如 想拿到 RequiredModule 中的 EmitterLoops,即循环次数,可以直接:
EmitterInstance ->CurrentLODLevel->RequiredModule->EmitterLoops
Particle System(PS) 是特效资源,在 Content 目录下鼠标悬停在资源上,就能看到介绍;
Particle System Component(PSC) 是实际播放特效的组件,在世界中创建出来的是这个,可以挂在人身上,也可以不挂。Cascade 中的预览窗口,也是创建了一个 PSC,不过还继承了一层。
/** Components used for drawing the particle system in the preview viewport */
UCascadeParticleSystemComponent* ParticleSystemComponent;
其中:
Emitter Duration Use Range
、 Emitter Duration Low
、Emitter Duration Low
- 用来将每次 Duration 设为一个范围的,一般不怎么用感觉;Emitter Loops
- 指这个发射器,循环多少次;0
表示无限循环,值得注意的是:这个值默认就是 0,而有一个发射器是无限循环的,那这个特效将会一直不销毁Emitter Duration
- 每一次发射的时长 在Spawn Module
中,可以设置粒子发射的速率,如果 0
(默认值),代表发射器每次虚幻,粒子就发射一次,如果是 1
,则表示发射器每次循环过程中,粒子每秒发射一次。
每个 Emitter 面板上有一个数字,代表这个粒子发射器,一次发射多少粒子。在 Viewport 里右下角也可以看到。
在 Viewport 中,左上角点 View
可以选更多展示的信息。
Cascade 中,右上方这些是 LOD 相关设置,其中:
Add LOD
- 对应 Add LOD Before
和 Add LOD After
,即在当前 LOD 和下个最高(最低)的 LOD 之间插入一个 LODLower LOD
和 Higher LOD
- 对应调到上一个或者下一个 LODLOD
- 就是当前 LOD 等级 选择一个 Emitter 后 Details 中显示的就是这个发射器的细节信息,如果想看整个特效的信息(比如 LOD),点一下右边的黑色空白区域即可。
可以在 Details 中看到 LOD 的设置:
这个地方,LODDistances
是不能添加的,需要用上边的 Add LOD
的按钮添加,这里自动就会添加了。
使用方法很简单,看注释就能看懂:
/**
* The array of distances for each LOD level in the system.
* Used when LODMethod is set to PARTICLESYSTEMLODMETHOD_Automatic.
*
* Example: System with 3 LOD levels
* LODDistances(0) = 0.0
* LODDistances(1) = 2500.0
* LODDistances(2) = 5000.0
*
* In this case, when the system is [ 0.0 .. 2499.9] from the camera, LOD level 0 will be used.
* [2500.0 .. 4999.9] from the camera, LOD level 1 will be used.
* [5000.0 .. INFINITY] from the camera, LOD level 2 will be used.
*
*/
UPROPERTY(EditAnywhere, editfixedsize, Category=LOD)
TArray<float> LODDistances;
越远的 LOD 特效应该越少,否则 LOD 就没有啥意义了,且不同 LOD 之间的设置不应该不一样,比如 SpawnRate
这种队表现影响非常大的参数。
根据官方 - Particle System Level of Detail (LOD) 的介绍,制作一个特效的 LOD 的步骤应该如下:
Create your overall desired effect. This will be the highest LOD level.
Next, create the lowest LOD level.
Add any other LOD levels between the two in order to create a smooth transition from highest quality to lowest.
注意:所有 Modules 都只能在最高层进行增加和删除操作。虽然可以这么做
在制作好最高层 LOD,特效人员觉得可以进行 LOD 的开发后,可以点击 Toolbar 中的 Regenerate Lowest LOD
或者 Regenerate Lowest LOD Duplicating Highest Button
按钮,区别在于,左边的按钮 是通过完全复制最高层,来生成一个最低层 LOD;而右边这个按钮 是生成一个最底层,并降低 Spawn Rate(亲测 Spawn Rate 会从 2 变成 0.2,降得还是挺多的)。
注意: 这个操作会删除现有的所有 LOD,除了最高等级的 LOD(会弹出一个确认框)。
降 SpawnRate 的代码如下,即默认是降到 10%,除了选完全复制最高层,以及目前不支持的 Beam 类型外。
bool UParticleEmitter::AutogenerateLowestLODLevel(bool bDuplicateHighest)
{
// blabla
float Percentage = 10.0f;
if (SourceLODLevel->TypeDataModule)
{
UParticleModuleTypeDataBeam2* Beam2TD = Cast<UParticleModuleTypeDataBeam2>(SourceLODLevel->TypeDataModule);
if (Beam2TD)
{
// For now, don't support LOD on beams and trails
Percentage = 100.0f;
}
}
if (bDuplicateHighest == true)
{
Percentage = 100.0f;
}
if (LODLevel->GenerateFromLODLevel(SourceLODLevel, Percentage) == false)
{
}
}
注意:LOD 默认距离是 2500(即 25 米),详见 void FCascade::RegenerateLowestLOD(bool bDupeHighest)
通过 Higher LOD 按钮(这里的 higher 指上边,其实是更低层级的 LOD),可以切到刚生成的最低级LOD,默认所有 Module 是 不能编辑 的(背景会有黑色花纹):
如果想编辑,在想编辑的 Module 上,右键然后选择 Duplicate from Highest
即可:
)
注意:: 对于 Emitter 来说,Detail 的信息(比如 Siginificance Level,Render Mode 等),只有在 LOD 0 是可以编辑的,其他层上都不能编辑,只能编辑 Module。
美术人员在制作特效后,需要确认不是循环的特效,这个 Emitter Loop
值不是 0,否则对效率和内存都有影响。
在 Cascade 的预览窗口(Viewport)中,点 Restart Level
然后看什么时候会出现 Complete
字样(Complete 代表这个特效要销毁了),可以大致知道这个特效会持续多久,如果很久没有出现,那就需要注意了,是不是 Emitter Duration
配的很长。
在 Viewport 窗口中,点 View
选择 View Modes -> Shader Complexity
,可以看到这个特效的复杂度,越红,复杂度越高。
运行时可以按 F5
切换成这个模式,白色说明性能已经非常差了!!
详见 Core Optimization Concepts for Particle Systems。
运行游戏,按 ~
键(1 左边那个),然后输入 Stat UNIT
,可以看到下图所示界面:
运行游戏,按 ~
键(1 左边那个),然后输入 Stat ParticlesOverview
(打了 stat particle 之后能看到还有一些其他选项),可以看到下图所示界面,播放特效后会显示数据:
其中:
GT
- 表示 Game ThreadRT
- 表示 Render Thread按理说,放一个技能之前是多少,放玩技能,特效都结束之后,这个数还应该是多少,如果结束很久了,这个 CallCount 还是变多了没有变化来,说明一定有特效时长/生命周期有问题。
输入 Stat StartFile
,然后正常进行游戏,或者针对性进行特定操作,然后 输入 Stat StopFile
,这时候在 \ARPG\ARPG\Saved\Profiling 目录下就会生成记录文件。
从 Window -> Developer Tools -> Session Frontend,中 Profiler 界面,Load 对应记录文件,就可以打开了。
里边数据很详细,比如 2.3.2 中的 GT concurrent Total
,可以通过搜索,搜出来,双击之后,可以在 Graph View 中看到最大最小,以及平均值。
在 Content 目录下,可以用 Filters 筛选出 Particle System
,如下图所示:
如果想要按照一些信息进行排序,可以在 Content 目录右下角,View Options
中选择 Columns
,就可以按不同数据进行排序了:
关于特效池,可以看第二篇 —— 【UE4】特效之 Particle System 详解(二)—— 特效池(本文中只需要知道一点,默认释放出来的特效,是没有放入池子管理的)。
这个由于太多了,也会写一篇单独的,