ShowFlag.PhysicsField

ShowFlag.PhysicsField

#Overview

name: ShowFlag.PhysicsField

This variable is created as a Console Variable (cvar).

It is referenced in 26 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of ShowFlag.PhysicsField is to control the visualization of physics fields in the Unreal Engine 5 rendering system. This show flag is used to toggle the visibility of physics field debug information in the game viewport.

The Physics Field system is primarily used in the Unreal Engine’s physics and rendering subsystems. Based on the provided code snippets, it interacts with the following modules and components:

  1. Chaos Cloth simulation
  2. Niagara particle system
  3. Animation system (RigidBody nodes)
  4. World and Scene management
  5. Field System components
  6. Geometry Collection components
  7. Deferred Shading Renderer

The value of this variable is set through the engine’s show flags system, which allows developers to toggle various debug visualization options in the editor and at runtime.

The ShowFlag.PhysicsField interacts closely with the World->PhysicsField object, which is an instance of UPhysicsFieldComponent. This component is responsible for managing and evaluating physics fields in the world.

Developers should be aware of the following when using this variable:

  1. It’s primarily used for debug visualization and should be disabled in shipping builds.
  2. Enabling this flag may have performance implications, especially in complex scenes with many physics fields.
  3. The visualization is rendered in the deferred shading pass, which means it may not be visible in forward rendering or mobile platforms.

Best practices when using this variable include:

  1. Use it during development and debugging phases to visualize and verify physics field behaviors.
  2. Ensure it’s disabled in release builds to avoid unnecessary performance overhead.
  3. Combine it with other debug tools and visualizations to get a comprehensive understanding of the physics simulation.

Regarding the associated variable PhysicsField, it is an instance of UPhysicsFieldComponent stored in the UWorld class. This component is responsible for managing physics fields in the world, including:

  1. Storing and evaluating field commands
  2. Providing interfaces for other systems (like cloth simulation and particle systems) to interact with physics fields
  3. Handling world origin shifts and other world-related operations

The PhysicsField component is created and managed by the UWorld class, and it’s used extensively throughout the engine to provide physics field functionality to various subsystems. Developers working with physics fields should familiarize themselves with the UPhysicsFieldComponent class and its methods to effectively utilize physics fields in their projects.

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:337

Scope: file

Source code excerpt:

SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeMeshDistanceFields, SFG_Visualize, NSLOCTEXT("UnrealEd", "MeshDistanceFieldsSF", "Mesh DistanceFields"))
/** Physics field */
SHOWFLAG_FIXED_IN_SHIPPING(0, PhysicsField, SFG_Visualize, NSLOCTEXT("UnrealEd", "PhysicsField", "Physics Field"))
/** Global Distance field */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeGlobalDistanceField, SFG_Visualize, NSLOCTEXT("UnrealEd", "GlobalDistanceFieldSF", "Global DistanceField"))
/** Enable the debug visualization of diffuse/specular lighting (direct and indirect) using probes */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeLightingOnProbes, SFG_Visualize, NSLOCTEXT("UnrealEd", "VisualizeLightingOnProbesSF", "Visualize Lighting on Probes"))
/** Screen space AO, for now SHOWFLAG_ALWAYS_ACCESSIBLE because r.GBuffer need that */
SHOWFLAG_ALWAYS_ACCESSIBLE(ScreenSpaceAO, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "ScreenSpaceAOSF", "Screen Space Ambient Occlusion"))

#Associated Variable and Callsites

This variable is associated with another variable named PhysicsField. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Plugins/ChaosCloth/Source/ChaosCloth/Private/ChaosCloth/ChaosClothingSimulation.cpp:397

Scope (from outer to inner):

file
function     void FClothingSimulation::UpdateWorldForces

Source code excerpt:

	{
		UWorld* OwnerWorld = OwnerComponent->GetWorld();
		if (OwnerWorld && OwnerWorld->PhysicsField && Solver)
		{
			const FBox BoundingBox = OwnerComponent->CalcBounds(OwnerComponent->GetComponentTransform()).GetBox();

			OwnerWorld->PhysicsField->FillTransientCommands(false, BoundingBox, Solver->GetTime(), Solver->GetPerSolverField().GetTransientCommands());
			OwnerWorld->PhysicsField->FillPersistentCommands(false, BoundingBox, Solver->GetTime(), Solver->GetPerSolverField().GetPersistentCommands());
		}
	}
}

void FClothingSimulation::ResetStats()
{

#Loc: <Workspace>/Engine/Plugins/Experimental/ChaosNiagara/Source/ChaosNiagara/Private/NiagaraDataInterfacePhysicsField.cpp:84

Scope (from outer to inner):

file
function     void FNDIPhysicsFieldData::Init

Source code excerpt:

			TimeSeconds = World->GetTimeSeconds();

			UPhysicsFieldComponent* FieldComponent = World->PhysicsField;
			if (FieldComponent && FieldComponent->FieldInstance && FieldComponent->FieldInstance->FieldResource)
			{
				FieldResource = FieldComponent->FieldInstance->FieldResource;
			}
		}
		LWCConverter = SystemInstance->GetLWCConverter();

#Loc: <Workspace>/Engine/Plugins/Experimental/ChaosNiagara/Source/ChaosNiagara/Private/NiagaraDataInterfacePhysicsField.cpp:103

Scope (from outer to inner):

file
function     void FNDIPhysicsFieldData::Update

Source code excerpt:

			TimeSeconds = World->GetTimeSeconds();

			UPhysicsFieldComponent* FieldComponent = World->PhysicsField;
			if (FieldComponent && FieldComponent->FieldInstance)
			{
				FieldCommands = FieldComponent->FieldInstance->FieldCommands;
			}
		}
	}

#Loc: <Workspace>/Engine/Plugins/Experimental/PhysicsControl/Source/PhysicsControl/Private/AnimNode_RigidBodyWithControl.cpp:1486

Scope (from outer to inner):

file
function     void FAnimNode_RigidBodyWithControl::PreUpdate

Source code excerpt:

			CurrentTransform = SKC->GetComponentToWorld();

			if (World->PhysicsField)
			{
				const FBox BoundingBox = SKC->CalcBounds(SKC->GetComponentTransform()).GetBox();

				World->PhysicsField->FillTransientCommands(false, BoundingBox, WorldTimeSeconds, PerSolverField.GetTransientCommands());
				World->PhysicsField->FillPersistentCommands(false, BoundingBox, WorldTimeSeconds, PerSolverField.GetPersistentCommands());
			}
		}
	}
}

int32 FAnimNode_RigidBodyWithControl::GetLODThreshold() const

#Loc: <Workspace>/Engine/Source/Runtime/AnimGraphRuntime/Private/BoneControllers/AnimNode_RigidBody.cpp:1531

Scope (from outer to inner):

file
function     void FAnimNode_RigidBody::PreUpdate

Source code excerpt:

			CurrentTransform = SKC->GetComponentToWorld();

			if (World->PhysicsField)
			{
				const FBox BoundingBox = SKC->CalcBounds(SKC->GetComponentTransform()).GetBox();

				PRAGMA_DISABLE_UNSAFE_TYPECAST_WARNINGS
				World->PhysicsField->FillTransientCommands(false, BoundingBox, WorldTimeSeconds, PerSolverField.GetTransientCommands());
				World->PhysicsField->FillPersistentCommands(false, BoundingBox, WorldTimeSeconds, PerSolverField.GetPersistentCommands());
				PRAGMA_RESTORE_UNSAFE_TYPECAST_WARNINGS
			}
		}
	}

	if (bUseExternalClothCollision && ClothColliders.IsEmpty())

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/World.h:1431

Scope (from outer to inner):

file
class        class UWorld final : public UObject, public FNetworkNotify

Source code excerpt:

	/** Physics Field component. */
	UPROPERTY(Transient)
	TObjectPtr<class UPhysicsFieldComponent> PhysicsField;

private:

	/** Array of components that need to wait on tasks before end of frame updates */
	UPROPERTY(Transient, NonTransactional)
	TSet<TObjectPtr<UActorComponent>> ComponentsThatNeedPreEndOfFrameSync;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsField/PhysicsFieldComponent.cpp:1229

Scope (from outer to inner):

file
function     FVector UPhysicsFieldStatics::EvalPhysicsVectorField

Source code excerpt:


		const EFieldPhysicsType PhysicsType = GetFieldTargetTypes(Field_Output_Vector)[TargetType];
		UPhysicsFieldComponent* FieldComponent = ThisWorld->PhysicsField;
		if (FieldComponent && FieldComponent->FieldInstance)
		{
			EvaluateFieldVectorNodes(FieldComponent->FieldInstance->FieldCommands, PhysicsType, FieldContext, SampleResults, SampleMax);
			return SampleMax[0];
		}
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsField/PhysicsFieldComponent.cpp:1260

Scope (from outer to inner):

file
function     float UPhysicsFieldStatics::EvalPhysicsScalarField

Source code excerpt:


		const EFieldPhysicsType PhysicsType = GetFieldTargetTypes(Field_Output_Scalar)[TargetType];
		UPhysicsFieldComponent* FieldComponent = ThisWorld->PhysicsField;
		if (FieldComponent && FieldComponent->FieldInstance)
		{
			EvaluateFieldScalarNodes(FieldComponent->FieldInstance->FieldCommands, PhysicsType, FieldContext, SampleResults, SampleMax);
			return SampleMax[0];
		}
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsField/PhysicsFieldComponent.cpp:1291

Scope (from outer to inner):

file
function     int32 UPhysicsFieldStatics::EvalPhysicsIntegerField

Source code excerpt:


		const EFieldPhysicsType PhysicsType = GetFieldTargetTypes(Field_Output_Scalar)[TargetType];
		UPhysicsFieldComponent* FieldComponent = ThisWorld->PhysicsField;
		if (FieldComponent && FieldComponent->FieldInstance)
		{
			EvaluateFieldIntegerNodes(FieldComponent->FieldInstance->FieldCommands, PhysicsType, FieldContext, SampleResults, SampleMax);
			return SampleMax[0];
		}
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/World.cpp:706

Scope (from outer to inner):

file
function     void UWorld::Serialize

Source code excerpt:

		Ar << PersistentLineBatcher;
		Ar << ForegroundLineBatcher;  
		Ar << PhysicsField;

		Ar << MyParticleEventManager;
		Ar << GameState;
		Ar << AuthorityGameMode;
		Ar << NetworkManager;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/World.cpp:777

Scope (from outer to inner):

file
function     void UWorld::AddReferencedObjects

Source code excerpt:

		Collector.AddReferencedObject( This->PersistentLineBatcher, This );
		Collector.AddReferencedObject( This->ForegroundLineBatcher, This );
		Collector.AddReferencedObject( This->PhysicsField, This);
		Collector.AddReferencedObject( This->MyParticleEventManager, This );
		Collector.AddReferencedObject( This->GameState, This );
		Collector.AddReferencedObject( This->AuthorityGameMode, This );
		Collector.AddReferencedObject( This->NetworkManager, This );
		Collector.AddReferencedObject( This->NavigationSystem, This );
		Collector.AddReferencedObject( This->AvoidanceManager, This );

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/World.cpp:2561

Scope (from outer to inner):

file
function     void UWorld::ClearWorldComponents

Source code excerpt:

	}

	if (PhysicsField && PhysicsField->IsRegistered())
	{
		PhysicsField->UnregisterComponent();
	}
}


void UWorld::UpdateWorldComponents(bool bRerunConstructionScripts, bool bCurrentLevelOnly, FRegisterComponentContext* Context)
{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/World.cpp:2614

Scope (from outer to inner):

file
function     void UWorld::UpdateWorldComponents

Source code excerpt:

		if (PhysicsFieldEnableClipmapCVar && PhysicsFieldEnableClipmapCVar->GetInt() == 1 && Scene && !IsMobilePlatform(Scene->GetShaderPlatform()))
		{
			if (!PhysicsField)
			{
				PhysicsField = NewObject<UPhysicsFieldComponent>();
			}

			if (!PhysicsField->IsRegistered())
			{
				PhysicsField->RegisterComponentWithWorld(this, Context);
			}
		}
	}

	if ( bCurrentLevelOnly )
	{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/World.cpp:7015

Scope (from outer to inner):

file
function     bool UWorld::SetNewWorldOrigin

Source code excerpt:

	}

	if (PhysicsField)
	{
		PhysicsField->ApplyWorldOffset(Offset, true);
	}

	FIntVector PreviosWorldOriginLocation = OriginLocation;
	// Set new world origin
	OriginLocation = InNewOriginLocation;
	RequestedOriginLocation = InNewOriginLocation;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:337

Scope: file

Source code excerpt:

SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeMeshDistanceFields, SFG_Visualize, NSLOCTEXT("UnrealEd", "MeshDistanceFieldsSF", "Mesh DistanceFields"))
/** Physics field */
SHOWFLAG_FIXED_IN_SHIPPING(0, PhysicsField, SFG_Visualize, NSLOCTEXT("UnrealEd", "PhysicsField", "Physics Field"))
/** Global Distance field */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeGlobalDistanceField, SFG_Visualize, NSLOCTEXT("UnrealEd", "GlobalDistanceFieldSF", "Global DistanceField"))
/** Enable the debug visualization of diffuse/specular lighting (direct and indirect) using probes */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeLightingOnProbes, SFG_Visualize, NSLOCTEXT("UnrealEd", "VisualizeLightingOnProbesSF", "Visualize Lighting on Probes"))
/** Screen space AO, for now SHOWFLAG_ALWAYS_ACCESSIBLE because r.GBuffer need that */
SHOWFLAG_ALWAYS_ACCESSIBLE(ScreenSpaceAO, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "ScreenSpaceAOSF", "Screen Space Ambient Occlusion"))

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/FieldSystem/Source/FieldSystemEngine/Private/Field/FieldSystemComponent.cpp:188

Scope (from outer to inner):

file
function     void UFieldSystemComponent::DispatchFieldCommand

Source code excerpt:

		{
			UWorld* World = GetWorld();
			if (World && World->PhysicsField)
			{
				FFieldSystemCommand LocalCommand = InCommand;
				LocalCommand.InitFieldNodes(World->GetTimeSeconds(), Name);

				if (!IsTransient)
				{

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/FieldSystem/Source/FieldSystemEngine/Private/Field/FieldSystemComponent.cpp:198

Scope (from outer to inner):

file
function     void UFieldSystemComponent::DispatchFieldCommand

Source code excerpt:

					{
						WorldGPUPersistentFields.Add(LocalCommand);
						World->PhysicsField->AddPersistentCommand(LocalCommand, true);
					}
					if (bIsChaosField)
					{
						WorldCPUPersistentFields.Add(LocalCommand);
						World->PhysicsField->AddPersistentCommand(LocalCommand, false);
					}
				}
				else
				{
					if (bIsWorldField)
					{
						World->PhysicsField->AddTransientCommand(LocalCommand, true);
					}
					if (bIsChaosField)
					{
						World->PhysicsField->AddTransientCommand(LocalCommand, false);
					}
				}
			}
		}
	}
}

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/FieldSystem/Source/FieldSystemEngine/Private/Field/FieldSystemComponent.cpp:253

Scope (from outer to inner):

file
function     void UFieldSystemComponent::ClearFieldCommands

Source code excerpt:

		{
			UWorld* World = GetWorld();
			if (World && World->PhysicsField)
			{
				if (bIsWorldField)
				{
					for (auto& FieldCommand : WorldGPUPersistentFields)
					{
						World->PhysicsField->RemovePersistentCommand(FieldCommand, true);
					}
				}
				if (bIsChaosField)
				{
					for (auto& FieldCommand : WorldCPUPersistentFields)
					{
						World->PhysicsField->RemovePersistentCommand(FieldCommand, false);
					}
				}
			}
		}
		WorldGPUPersistentFields.Reset();
		WorldCPUPersistentFields.Reset();

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/FieldSystem/Source/FieldSystemEngine/Private/Field/FieldSystemComponent.cpp:298

Scope (from outer to inner):

file
function     void UFieldSystemComponent::AddFieldCommand

Source code excerpt:


				UWorld* World = GetWorld();
				if (World && World->PhysicsField)
				{
					const FName Name = GetOwner() ? *GetOwner()->GetName() : TEXT("");

					FFieldSystemCommand LocalCommand = Command;
					LocalCommand.InitFieldNodes(World->GetTimeSeconds(), Name);

					World->PhysicsField->AddConstructionCommand(LocalCommand);
				}
			}
		}

		BufferCommands.AddFieldCommand(GetFieldPhysicsName(Target), Field, MetaData);
	}

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/GeometryCollectionEngine/Private/GeometryCollection/GeometryCollectionComponent.cpp:5876

Scope (from outer to inner):

file
function     void UGeometryCollectionComponent::GetInitializationCommands

Source code excerpt:


							UWorld* World = GetWorld();
							if (World && World->PhysicsField)
							{
								const FName Name = GetOwner() ? *GetOwner()->GetName() : TEXT("");

								FFieldSystemCommand LocalCommand = NewCommand;
								LocalCommand.InitFieldNodes(World->GetTimeSeconds(), Name);

								World->PhysicsField->AddConstructionCommand(LocalCommand);
							}
						}
					}
				}
				// Legacy path : only there for old levels. New ones will have the commands directly stored onto the component
				else if (FieldSystemActor->GetFieldSystemComponent()->GetFieldSystem())

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:3217

Scope (from outer to inner):

file
function     void FDeferredShadingSceneRenderer::Render

Source code excerpt:

		RendererModule.RenderOverlayExtensions(GraphBuilder, Views, SceneTextures);

		if (ViewFamily.EngineShowFlags.PhysicsField && Scene->PhysicsField)
		{
			RenderPhysicsField(GraphBuilder, Views, Scene->PhysicsField, SceneTextures.Color.Target);
		}

		if (ViewFamily.EngineShowFlags.VisualizeDistanceFieldAO && ShouldRenderDistanceFieldLighting())
		{
			GraphBuilder.SetCommandListStat(GET_STATID(STAT_CLM_RenderDistanceFieldLighting));

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/RendererScene.cpp:2913

Scope (from outer to inner):

file
function     void FScene::SetPhysicsField
lambda-function

Source code excerpt:

		[Scene, PhysicsFieldSceneProxy] (FRHICommandListBase&)
		{
			Scene->PhysicsField = PhysicsFieldSceneProxy;
		});
}

void FScene::ShowPhysicsField()
{
	// Set the shader print/debug values from game thread if
	// physics field visualisation has been enabled
	if (PhysicsField && PhysicsField->FieldResource && PhysicsField->FieldResource->FieldInfos.bShowFields)
	{
		// Force ShaderPrint on.
		ShaderPrint::SetEnabled(true);
		ShaderPrint::RequestSpaceForLines(128000);
	}
}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/RendererScene.cpp:2936

Scope (from outer to inner):

file
function     void FScene::ResetPhysicsField
lambda-function

Source code excerpt:

		[Scene] (FRHICommandListBase&)
		{
			Scene->PhysicsField = nullptr;
		});
}

void FScene::UpdatePhysicsField(FRDGBuilder& GraphBuilder, FViewInfo& View)
{
	if (PhysicsField)
	{
		PhysicsField->FieldResource->FieldInfos.ViewOrigin = View.ViewMatrices.GetViewOrigin();
		if (View.Family )
		{
			PhysicsField->FieldResource->FieldInfos.bShowFields = View.Family->EngineShowFlags.PhysicsField;
		}
	}
}

void FScene::AddDecal(UDecalComponent* Component)
{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ScenePrivate.h:3150

Scope (from outer to inner):

file
class        class FScene : public FSceneInterface

Source code excerpt:


	/** Global Field Manager */
	class FPhysicsFieldSceneProxy* PhysicsField = nullptr;

	/** The wind sources in the scene. */
	TArray<class FWindSourceSceneProxy*> WindSources;

	/** Wind source components, tracked so the game thread can also access wind parameters */
	TArray<UWindDirectionalSourceComponent*> WindComponents_GameThread;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneRendering.cpp:1193

Scope (from outer to inner):

file
function     void SetupPhysicsFieldUniformBufferParameters

Source code excerpt:

void SetupPhysicsFieldUniformBufferParameters(const FScene* Scene, FEngineShowFlags EngineShowFlags, FViewUniformShaderParameters& ViewUniformShaderParameters)
{
	if (Scene && Scene->PhysicsField && Scene->PhysicsField->FieldResource)
	{
		FPhysicsFieldResource* FieldResource = Scene->PhysicsField->FieldResource;
		if (FieldResource->FieldInfos.bBuildClipmap)
		{
			ViewUniformShaderParameters.PhysicsFieldClipmapBuffer = FieldResource->ClipmapBuffer.SRV.GetReference();
		}
		else
		{