p.ClothPhysics
p.ClothPhysics
#Overview
name: p.ClothPhysics
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
If 1, physics cloth will be used for simulation.
It is referenced in 10
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of p.ClothPhysics is to control whether physics cloth simulation is used in the game. It is a console variable that can be used to enable or disable cloth physics simulation at runtime.
This setting variable is primarily used by the cloth simulation system in Unreal Engine 5. It is utilized by the following subsystems and modules:
- The Skeletal Mesh Component system
- The Chaos Cloth Asset Engine plugin
- The general cloth simulation system
The value of this variable is set through the console command system. It is initialized with a default value of 1, which means cloth physics is enabled by default. The value can be changed at runtime using console commands.
The associated variable CVarEnableClothPhysics interacts directly with p.ClothPhysics. They share the same value and are used interchangeably in the code.
Developers must be aware of the following when using this variable:
- Setting it to 0 will disable cloth physics simulation entirely.
- It affects performance, as enabling cloth physics requires additional computation.
- It is marked with ECVF_Scalability, indicating it’s intended to be used for performance scaling.
Best practices when using this variable include:
- Use it for performance optimization, enabling or disabling cloth physics based on the target hardware capabilities.
- Consider exposing it as a user-configurable setting for players to adjust based on their system performance.
- Be aware that disabling cloth physics may affect the visual quality of clothing in the game.
Regarding the associated variable CVarEnableClothPhysics:
The purpose of CVarEnableClothPhysics is the same as p.ClothPhysics - to control whether cloth physics simulation is enabled.
It is used in various parts of the skeletal mesh component system to check if cloth simulation should be performed. This includes functions like CanSimulateClothing(), TickComponent(), and RecreateClothingActors().
The value of CVarEnableClothPhysics is set automatically based on the value of p.ClothPhysics.
Developers should be aware that this variable is often checked in performance-critical code paths, so changing its value can have significant performance implications.
Best practices for CVarEnableClothPhysics are the same as for p.ClothPhysics, as they are essentially two ways of accessing the same setting.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:48
Scope: file
Source code excerpt:
CSV_DECLARE_CATEGORY_MODULE_EXTERN(CORE_API, Basic);
TAutoConsoleVariable<int32> CVarEnableClothPhysics(TEXT("p.ClothPhysics"), 1, TEXT("If 1, physics cloth will be used for simulation."), ECVF_Scalability);
static TAutoConsoleVariable<int32> CVarEnableClothPhysicsUseTaskThread(TEXT("p.ClothPhysics.UseTaskThread"), 1, TEXT("If 1, run cloth on the task thread. If 0, run on game thread."));
static TAutoConsoleVariable<int32> CVarClothPhysicsTickWaitForParallelClothTask(TEXT("p.ClothPhysics.WaitForParallelClothTask"), 0, TEXT("If 1, always wait for cloth task completion in the Cloth Tick function. If 0, wait at end-of-frame updates instead if allowed by component settings"));
static TAutoConsoleVariable<bool> CVarClothTeleportOverride(TEXT("p.Cloth.TeleportOverride"), false, TEXT("Force console variable teleport override values over skeletal mesh properties.\n Default: false."));
static TAutoConsoleVariable<bool> CVarClothResetAfterTeleport(TEXT("p.Cloth.ResetAfterTeleport"), true, TEXT("Require p.Cloth.TeleportOverride. Reset the clothing after moving the clothing position (called teleport).\n Default: true."));
#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothComponent.cpp:55
Scope (from outer to inner):
file
function bool UChaosClothComponent::IsSimulationSuspended
Source code excerpt:
bool UChaosClothComponent::IsSimulationSuspended() const
{
static IConsoleVariable* const CVarClothPhysics = IConsoleManager::Get().FindConsoleVariable(TEXT("p.ClothPhysics"));
return bSuspendSimulation || !ClothSimulationProxy.IsValid() || (CVarClothPhysics && !CVarClothPhysics->GetBool());
}
bool UChaosClothComponent::IsSimulationEnabled() const
{
static IConsoleVariable* const CVarClothPhysics = IConsoleManager::Get().FindConsoleVariable(TEXT("p.ClothPhysics"));
// If the console variable doesn't exist, default to simulation enabled.
return bEnableSimulation && ClothSimulationProxy.IsValid() && (!CVarClothPhysics || CVarClothPhysics->GetBool());
}
void UChaosClothComponent::ResetConfigProperties()
{
#Associated Variable and Callsites
This variable is associated with another variable named CVarEnableClothPhysics
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkeletalMeshComponent.cpp:594
Scope: file
Source code excerpt:
}
extern TAutoConsoleVariable<int32> CVarEnableClothPhysics;
bool USkeletalMeshComponent::CanSimulateClothing() const
{
if(!GetSkeletalMeshAsset() || !bAllowClothActors || !CVarEnableClothPhysics.GetValueOnAnyThread())
{
return false;
}
return GetSkeletalMeshAsset()->HasActiveClothingAssets() && !IsNetMode(NM_DedicatedServer);
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/SkeletalMeshComponent.cpp:1700
Scope (from outer to inner):
file
function void USkeletalMeshComponent::TickComponent
Source code excerpt:
// If we are suspended, we will not simulate clothing, but as clothing is simulated in local space
// relative to a root bone we need to extract simulation positions as this bone could be animated.
if((!CVarEnableClothPhysics.GetValueOnGameThread() || bClothingSimulationSuspended) && ClothingSimulation)
{
CSV_SCOPED_TIMING_STAT(Animation, Cloth);
// First update the simulation context, since the simulation isn't ticking
// and it is still required to get the correct simulation data and bounds.
constexpr bool bIsInitialization = false;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:48
Scope: file
Source code excerpt:
CSV_DECLARE_CATEGORY_MODULE_EXTERN(CORE_API, Basic);
TAutoConsoleVariable<int32> CVarEnableClothPhysics(TEXT("p.ClothPhysics"), 1, TEXT("If 1, physics cloth will be used for simulation."), ECVF_Scalability);
static TAutoConsoleVariable<int32> CVarEnableClothPhysicsUseTaskThread(TEXT("p.ClothPhysics.UseTaskThread"), 1, TEXT("If 1, run cloth on the task thread. If 0, run on game thread."));
static TAutoConsoleVariable<int32> CVarClothPhysicsTickWaitForParallelClothTask(TEXT("p.ClothPhysics.WaitForParallelClothTask"), 0, TEXT("If 1, always wait for cloth task completion in the Cloth Tick function. If 0, wait at end-of-frame updates instead if allowed by component settings"));
static TAutoConsoleVariable<bool> CVarClothTeleportOverride(TEXT("p.Cloth.TeleportOverride"), false, TEXT("Force console variable teleport override values over skeletal mesh properties.\n Default: false."));
static TAutoConsoleVariable<bool> CVarClothResetAfterTeleport(TEXT("p.Cloth.ResetAfterTeleport"), true, TEXT("Require p.Cloth.TeleportOverride. Reset the clothing after moving the clothing position (called teleport).\n Default: true."));
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:2735
Scope (from outer to inner):
file
function void USkeletalMeshComponent::RecreateClothingActors
Source code excerpt:
}
if(CVarEnableClothPhysics.GetValueOnGameThread() && (SkelMesh->GetMeshClothingAssets().Num() > 0))
{
UClass* SimFactoryClass = *ClothingSimulationFactory;
if (SimFactoryClass)
{
UClothingSimulationFactory* SimFactory = SimFactoryClass->GetDefaultObject<UClothingSimulationFactory>();
if(ClothingSimulation == nullptr)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:3720
Scope (from outer to inner):
file
function bool USkeletalMeshComponent::RequiresPreEndOfFrameSync
Source code excerpt:
bool USkeletalMeshComponent::RequiresPreEndOfFrameSync() const
{
if ((ClothingSimulation != nullptr) && (CVarEnableClothPhysics.GetValueOnGameThread() != 0))
{
// By default we await the cloth task in the ClothTickFunction, but...
// If we have cloth and have no game-thread dependencies on the cloth output,
// then we will wait for the cloth task in SendAllEndOfFrameUpdates.
if (!ShouldWaitForClothInTickFunction())
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:3782
Scope (from outer to inner):
file
function void USkeletalMeshComponent::UpdateClothStateAndSimulate
Source code excerpt:
// If disabled or no simulation
if (CVarEnableClothPhysics.GetValueOnGameThread() == 0 || !ClothingSimulation || bDisableClothSimulation)
{
return;
}
// If we simulate a clothing actor at 0s it will fill simulated positions and normals with NaNs.
// we can skip all the work it is still doing, and get the desired result (frozen sim) by not
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:3856
Scope (from outer to inner):
file
function void USkeletalMeshComponent::TickClothing
Source code excerpt:
bIsCompiling = (GetSkeletalMeshAsset() && GetSkeletalMeshAsset()->IsCompiling());
#endif
if (GetSkeletalMeshAsset() == nullptr || !ClothingSimulation || CVarEnableClothPhysics.GetValueOnGameThread() == 0 || bIsCompiling)
{
return;
}
// Use the component update flag to gate simulation to respect the always tick options
bool bShouldTick = ((VisibilityBasedAnimTickOption < EVisibilityBasedAnimTickOption::OnlyTickPoseWhenRendered) || bRecentlyRendered);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkeletalMeshComponentPhysics.cpp:3876
Scope (from outer to inner):
file
function void USkeletalMeshComponent::GetUpdateClothSimulationData
Source code excerpt:
void USkeletalMeshComponent::GetUpdateClothSimulationData(TMap<int32, FClothSimulData>& OutClothSimData, USkeletalMeshComponent* OverrideLocalRootComponent)
{
if(CVarEnableClothPhysics.GetValueOnAnyThread() == 0)
{
return;
}
SCOPE_CYCLE_COUNTER(STAT_ClothTotalTime);
CSV_SCOPED_TIMING_STAT(Animation, Cloth);