FX.FreezeParticleSimulation
FX.FreezeParticleSimulation
#Overview
name: FX.FreezeParticleSimulation
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Freeze particle simulation.
It is referenced in 11
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of FX.FreezeParticleSimulation is to control the freezing of particle simulation in Unreal Engine’s visual effects system. This setting variable is used to pause or resume the simulation of particles, which is particularly useful for debugging, performance analysis, or creating specific visual effects.
This setting variable is primarily used in the Engine’s particle system and visual effects modules. Based on the callsites, it’s utilized in the following subsystems:
- FXSystem (Particles/FXSystem.cpp)
- ParticleComponents (Particles/ParticleComponents.cpp)
- ParticleGpuSimulation (Particles/ParticleGpuSimulation.cpp)
- ParticleSystemManager (Particles/ParticleSystemManager.cpp)
The value of this variable is set through the console variable system. It can be modified using console commands or through the level editor actions (LevelEditorActions.cpp).
FX.FreezeParticleSimulation interacts with several other variables and systems:
- It’s associated with the bFreezeParticleSimulation variable, which shares the same value.
- It’s often used in conjunction with FX.FreezeGPUSimulation and FX.AllowAsyncTick.
- It affects both CPU and GPU particle simulations.
Developers should be aware of the following when using this variable:
- It’s marked as a cheat variable (ECVF_Cheat), indicating it should not be used in production builds.
- Freezing particle simulation can affect gameplay and visual fidelity, so it should be used carefully in development and debugging scenarios.
- It impacts both CPU and GPU particle simulations, potentially affecting performance metrics.
Best practices when using this variable include:
- Use it primarily for debugging and performance analysis.
- Remember to unfreeze the simulation when done to avoid unexpected behavior.
- Consider the impact on both CPU and GPU simulations when freezing particles.
- Use in conjunction with other debugging tools to get a comprehensive view of particle system performance.
Regarding the associated variable bFreezeParticleSimulation:
The purpose of bFreezeParticleSimulation is to act as the internal representation of the FX.FreezeParticleSimulation console variable. It’s used directly in the engine code to control particle simulation freezing.
This variable is used in the same subsystems as FX.FreezeParticleSimulation, primarily in the particle and visual effects modules of the engine.
The value of bFreezeParticleSimulation is set through the console variable system, mirroring the value of FX.FreezeParticleSimulation.
It interacts closely with FX.FreezeParticleSimulation and is often checked in conjunction with other particle system variables like bFreezeGPUSimulation and bAllowAsyncTick.
Developers should be aware that this is an internal variable and should generally interact with it through the FX.FreezeParticleSimulation console variable rather than directly.
Best practices for bFreezeParticleSimulation are similar to those for FX.FreezeParticleSimulation, focusing on its use in debugging and development scenarios rather than in production code.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/FXSystem.cpp:158
Scope (from outer to inner):
file
namespace FXConsoleVariables
Source code excerpt:
);
FAutoConsoleVariableRef CVarFreezeParticleSimulation(
TEXT("FX.FreezeParticleSimulation"),
bFreezeParticleSimulation,
TEXT("Freeze particle simulation."),
ECVF_Cheat
);
FAutoConsoleVariableRef CVarAllowAsyncTick(
TEXT("FX.AllowAsyncTick"),
#Loc: <Workspace>/Engine/Source/Editor/LevelEditor/Private/LevelEditorActions.cpp:2805
Scope (from outer to inner):
file
function void FLevelEditorActionCallbacks::OnToggleFreezeParticleSimulation
Source code excerpt:
{
IConsoleManager& ConsoleManager = IConsoleManager::Get();
IConsoleVariable* CVar = ConsoleManager.FindConsoleVariable(TEXT("FX.FreezeParticleSimulation"));
if (CVar)
{
CVar->Set(CVar->GetInt() == 0 ? 1 : 0, ECVF_SetByConsole);
}
}
#Loc: <Workspace>/Engine/Source/Editor/LevelEditor/Private/LevelEditorActions.cpp:2815
Scope (from outer to inner):
file
function bool FLevelEditorActionCallbacks::OnIsParticleSimulationFrozen
Source code excerpt:
{
IConsoleManager& ConsoleManager = IConsoleManager::Get();
static const auto* CVar = ConsoleManager.FindConsoleVariable(TEXT("FX.FreezeParticleSimulation"));
if (CVar)
{
return CVar->GetInt() != 0;
}
return false;
}
#Associated Variable and Callsites
This variable is associated with another variable named bFreezeParticleSimulation
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/FXSystem.cpp:125
Scope (from outer to inner):
file
namespace FXConsoleVariables
Source code excerpt:
int32 bAllowCulling = true;
int32 bFreezeGPUSimulation = false;
int32 bFreezeParticleSimulation = false;
int32 bAllowAsyncTick = !WITH_EDITOR;
float ParticleSlackGPU = 0.02f;
int32 MaxParticleTilePreAllocation = 100;
int32 MaxCPUParticlesPerEmitter = 1000;
int32 MaxGPUParticlesSpawnedPerFrame = 1024 * 1024;
int32 GPUSpawnWarningThreshold = 20000;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/FXSystem.cpp:159
Scope (from outer to inner):
file
namespace FXConsoleVariables
Source code excerpt:
FAutoConsoleVariableRef CVarFreezeParticleSimulation(
TEXT("FX.FreezeParticleSimulation"),
bFreezeParticleSimulation,
TEXT("Freeze particle simulation."),
ECVF_Cheat
);
FAutoConsoleVariableRef CVarAllowAsyncTick(
TEXT("FX.AllowAsyncTick"),
bAllowAsyncTick,
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleComponents.cpp:5545
Scope (from outer to inner):
file
function void UParticleSystemComponent::TickComponent
Source code excerpt:
if (!IsTickManaged() || bWarmingUp)
{
if (!ThisTickFunction || !ThisTickFunction->IsCompletionHandleValid() || !CanTickInAnyThread() || FXConsoleVariables::bFreezeParticleSimulation || !FXConsoleVariables::bAllowAsyncTick || !FApp::ShouldUseThreadingForPerformance() ||
GDistributionType == 0) // this may not be absolutely required, however if you are using distributions it will be glacial anyway. If you want to get rid of this, note that some modules use this indirectly as their criteria for CanTickInAnyThread
{
bDisallowAsync = true;
}
if (bDisallowAsync)
{
if (!FXConsoleVariables::bFreezeParticleSimulation)
{
ComputeTickComponent_Concurrent();
}
FinalizeTickComponent();
}
else
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleComponents.cpp:5713
Scope (from outer to inner):
file
function void UParticleSystemComponent::FinalizeTickComponent
Source code excerpt:
bNeedsFinalize = false;
if (FXConsoleVariables::bFreezeParticleSimulation == false)
{
int32 EmitterIndex;
// Now, process any events that have occurred.
for (EmitterIndex = 0; EmitterIndex < EmitterInstances.Num(); EmitterIndex++)
{
FParticleEmitterInstance* Instance = EmitterInstances[EmitterIndex];
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:3385
Scope (from outer to inner):
file
class class FGPUSpriteParticleEmitterInstance : public FParticleEmitterInstance
function virtual FDynamicEmitterDataBase* GetDynamicData
Source code excerpt:
const bool bSimulateGPUParticles =
FXConsoleVariables::bFreezeGPUSimulation == false &&
FXConsoleVariables::bFreezeParticleSimulation == false &&
RHISupportsGPUParticles();
if (bSimulateGPUParticles)
{
float& DeltaSecondsInFix = DynamicData->PerFrameSimulationParameters.DeltaSecondsInFix;
int32& NumIterationsInFix = DynamicData->PerFrameSimulationParameters.NumIterationsInFix;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleGpuSimulation.cpp:3603
Scope (from outer to inner):
file
class class FGPUSpriteParticleEmitterInstance : public FParticleEmitterInstance
function virtual void Tick
Source code excerpt:
if (FXConsoleVariables::bFreezeGPUSimulation ||
FXConsoleVariables::bFreezeParticleSimulation ||
!RHISupportsGPUParticles())
{
return;
}
// Grab the current LOD level
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Particles/ParticleSystemManager.cpp:742
Scope (from outer to inner):
file
function void FParticleSystemWorldManager::Tick
Source code excerpt:
//UE_LOG(LogParticles, Warning, TEXT("| Queue Concurrent Ticks | TG: %s |"), *TickGroupEnum->GetNameByValue(TickGroup).ToString());
bool bAllowTickConcurrent = !FXConsoleVariables::bFreezeParticleSimulation && FXConsoleVariables::bAllowAsyncTick && FApp::ShouldUseThreadingForPerformance() && GDistributionType != 0;
if (bAllowTickConcurrent)
{
//TODO: Currently waiting on this tick group but we should be able to allow these tasks to run over the whole frame if we can implement some synchronization so they don't overrun the EOF updates.
ProcessTickList<true>(DeltaTime, TickType, TickGroup, TickLists_Concurrent, MyCompletionGraphEvent);
}
else
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/FXSystem.h:69
Scope (from outer to inner):
file
namespace FXConsoleVariables
Source code excerpt:
extern int32 bFreezeGPUSimulation;
/** true if particle simulation is frozen. */
extern int32 bFreezeParticleSimulation;
/** true if we allow async ticks */
extern int32 bAllowAsyncTick;
/** Amount of slack to allocate for GPU particles to prevent tile churn as percentage of total particles. */
extern float ParticleSlackGPU;
/** Maximum tile preallocation for GPU particles. */
extern int32 MaxParticleTilePreAllocation;