MaxDeltaTime

MaxDeltaTime

#Overview

name: MaxDeltaTime

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 30 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of MaxDeltaTime is to limit the maximum time step used in physics simulations and other time-dependent calculations within Unreal Engine. It serves as a safeguard to prevent large, unrealistic jumps in simulation that can occur when frame rates drop or during other scenarios where the time between frames becomes unusually large.

MaxDeltaTime is primarily used in the following Unreal Engine subsystems and modules:

  1. Physics simulation (Chaos)
  2. Animation systems (AnimGraphRuntime)
  3. Niagara particle systems
  4. Game Engine time management
  5. Cloth simulation

The value of MaxDeltaTime is typically set in the engine configuration or within specific system settings. For example, in the GameEngine class, it’s a configurable property.

MaxDeltaTime often interacts with other time-related variables such as DeltaTime, MinDeltaTime, and various time step calculations.

Developers should be aware that:

  1. Setting MaxDeltaTime too low can result in slow-motion effects or performance issues when the frame rate drops.
  2. Setting it too high might lead to simulation instabilities or unrealistic behavior.
  3. Different systems may have their own MaxDeltaTime settings, which should be tuned individually for optimal results.

Best practices when using MaxDeltaTime include:

  1. Adjust it based on the specific needs of your game or simulation.
  2. Use it in conjunction with other time step controls for more precise behavior.
  3. Consider the target frame rate and minimum acceptable performance when setting this value.
  4. Test thoroughly with various performance scenarios to ensure stability and consistent behavior.
  5. For physics-heavy games, coordinate MaxDeltaTime settings across different systems (e.g., animation, particle effects, and physics) for consistent results.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:1366, section: [/Script/Engine.GameEngine]

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationContext.cpp:11

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
function     void FClothSimulationContext::Fill

Source code excerpt:

namespace UE::Chaos::ClothAsset
{
	void FClothSimulationContext::Fill(const UChaosClothComponent& ClothComponent, float InDeltaTime, float MaxDeltaTime, bool bIsInitialization, FClothingSimulationCacheData* InCacheData)
	{
		// Set the time
		DeltaTime = FMath::Min(InDeltaTime, MaxDeltaTime);

		// Set the current LOD index
		LodIndex = ClothComponent.GetPredictedLODLevel();

		// Set the teleport mode
		static const IConsoleVariable* const CVarMaxDeltaTimeTeleportMultiplier = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Cloth.MaxDeltaTimeTeleportMultiplier"));

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationContext.cpp:24

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
function     void FClothSimulationContext::Fill

Source code excerpt:

		const float MaxDeltaTimeTeleportMultiplier = CVarMaxDeltaTimeTeleportMultiplier ? CVarMaxDeltaTimeTeleportMultiplier->GetFloat() : MaxDeltaTimeTeleportMultiplierDefault;

		bTeleport = (DeltaTime > MaxDeltaTime * MaxDeltaTimeTeleportMultiplier) ? true : ClothComponent.NeedsTeleport();
		bReset = ClothComponent.NeedsReset();

		VelocityScale = (!bTeleport && !bReset && InDeltaTime > 0.f) ?
			FMath::Min(InDeltaTime, MaxDeltaTime) / InDeltaTime :
			bReset ? 1.f : 0.f;  // Set to 0 when teleporting and 1 when resetting to match the internal solver's behavior

		// Copy component transform
		ComponentTransform = ClothComponent.GetComponentTransform();

		// Update bone transforms

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationContext.h:52

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset

Source code excerpt:


		/** Fill the context from data collected from the specified component. */
		void Fill(const UChaosClothComponent& ClothComponent, float InDeltaTime, float MaxDeltaTime, bool bIsInitialization = false, FClothingSimulationCacheData* CacheData = nullptr);
	};
}

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationProxy.cpp:93

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
function     FClothSimulationProxy::FClothSimulationProxy

Source code excerpt:

		, Solver(nullptr)
		, Visualization(nullptr)
		, MaxDeltaTime(UPhysicsSettings::Get()->MaxPhysicsDeltaTime)
	{
		using namespace ::Chaos;

		check(IsInGameThread());

		// Create solver config simulation thread object first. Need to know which solver type we're creating.

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationProxy.cpp:110

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
function     FClothSimulationProxy::FClothSimulationProxy

Source code excerpt:

		constexpr bool bIsInitialization = true;
		constexpr Softs::FSolverReal NoAdvanceDt = 0.f;
		ClothSimulationContext->Fill(ClothComponent, NoAdvanceDt, MaxDeltaTime, bIsInitialization);

		// Setup startup transforms
		constexpr bool bNeedsReset = true;
		Solver->SetLocalSpaceLocation((FVec3)ClothSimulationContext->ComponentTransform.GetLocation(), bNeedsReset);
		Solver->SetLocalSpaceRotation((FQuat)ClothSimulationContext->ComponentTransform.GetRotation());

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationProxy.cpp:165

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
function     FClothSimulationProxy::FClothSimulationProxy

Source code excerpt:


		// Set start pose (update the context, then the solver without advancing the simulation)
		ClothSimulationContext->Fill(ClothComponent, NoAdvanceDt, MaxDeltaTime);
		Solver->Update((Softs::FSolverReal)ClothSimulationContext->DeltaTime);
	}

	FClothSimulationProxy::~FClothSimulationProxy()
	{
		CompleteParallelSimulation_GameThread();

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Private/ChaosClothAsset/ClothSimulationProxy.cpp:526

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
function     void FClothSimulationProxy::FillSimulationContext

Source code excerpt:

	void FClothSimulationProxy::FillSimulationContext(float DeltaTime, bool bIsInitialization)
	{
		ClothSimulationContext->Fill(ClothComponent, DeltaTime, MaxDeltaTime, bIsInitialization, CacheData.Get());
		CacheData.Reset();
	}

	bool FClothSimulationProxy::ShouldEnableSolver(bool bSolverCurrentlyEnabled) const
	{
		switch (SolverMode)

#Loc: <Workspace>/Engine/Plugins/ChaosClothAsset/Source/ChaosClothAssetEngine/Public/ChaosClothAsset/ClothSimulationProxy.h:135

Scope (from outer to inner):

file
namespace    UE::Chaos::ClothAsset
class        class FClothSimulationProxy

Source code excerpt:


		// Cached value of the MaxPhysicsDeltaTime setting for the life of this proxy
		const float MaxDeltaTime;
	};

#if !defined(CHAOS_TRANSFORM_CLOTH_SIMUL_DATA_ISPC_ENABLED_DEFAULT)
#define CHAOS_TRANSFORM_CLOTH_SIMUL_DATA_ISPC_ENABLED_DEFAULT 1
#endif

#Loc: <Workspace>/Engine/Plugins/Developer/Concert/ConcertSync/ConcertSyncTest/Source/ConcertSyncTest/Private/Replication/FrequencyTests.cpp:121

Scope (from outer to inner):

file
namespace    UE::ConcertSyncTests::Replication::Frequency

Source code excerpt:

			constexpr double AcceptableTimeRange = UpdateIntervalSeconds * 0.01;
			constexpr double MinDeltaTime = UpdateIntervalSeconds - AcceptableTimeRange;
			constexpr double MaxDeltaTime = UpdateIntervalSeconds + AcceptableTimeRange;
			if (bReceivedServer)
			{
				const bool bMin = MinDeltaTime <= DeltaSecSinceLast_Server || bIsFirstServerReceive;
				const bool bMax = DeltaSecSinceLast_Server <= MaxDeltaTime || bIsFirstServerReceive;
				AddErrorIfFalse(bMin, FString::Printf(TEXT("Server: MinDeltaTime (%f) <= DeltaSecSinceLast_Server (%f)"), MinDeltaTime, DeltaSecSinceLast_Server));
				AddErrorIfFalse(bMax, FString::Printf(TEXT("Server: DeltaSecSinceLast_Server (%f) <= MaxDeltaTime (%f)"), DeltaSecSinceLast_Server, MaxDeltaTime));
				bIsFirstServerReceive = false;
			}
			if (bReceivedClient)
			{
				const bool bMin = MinDeltaTime <= DeltaSecSinceLast_Client || bIsFirstClientReceive;
				const bool bMax = DeltaSecSinceLast_Client <= MaxDeltaTime || bIsFirstClientReceive;
				AddErrorIfFalse(bMin, FString::Printf(TEXT("Client: MinDeltaTime (%f) <= DeltaSecSinceLast_Client (%f)"), MinDeltaTime, DeltaSecSinceLast_Client));
				AddErrorIfFalse(bMax, FString::Printf(TEXT("Client: DeltaSecSinceLast_Client (%f) <= MaxDeltaTime (%f)"), DeltaSecSinceLast_Client, MaxDeltaTime));
				bIsFirstClientReceive = false;
			}
		}

		// 2.2 Verify that the expected number of events was received in the past 1 second
		// We may be off by one event due to double rounding errors
		constexpr uint8 AcceptableDropAmount = 1;
		constexpr uint8 MinExpected = GetUpdateRate() - AcceptableDropAmount;
		constexpr uint8 MaxExpected = GetUpdateRate();
		AddErrorIfFalse(MinExpected <= NumServerReceived, FString::Printf(TEXT("Server: MinExpected (%d)<= NumServerReceived (%d)"), MinExpected, NumServerReceived));
		AddErrorIfFalse(NumServerReceived <= MaxExpected, FString::Printf(TEXT("Server: NumServerReceived (%d) <= MaxExpected (%d)"), NumServerReceived, MaxExpected));
		AddErrorIfFalse(MinExpected <= NumClientReceived, FString::Printf(TEXT("Server: MinExpected (%d)<= NumClientReceived (%d)"), MinExpected, NumClientReceived));
		AddErrorIfFalse(NumClientReceived <= MaxExpected, FString::Printf(TEXT("Server: NumClientReceived (%d) <= MaxExpected (%d)"), NumClientReceived, MaxExpected));

		// 2.1 (time between updates) and 2.2 (number of updates) correctly test that we replicate at the expected frequency.
		return true;
	}*/
}

#endif

#Loc: <Workspace>/Engine/Plugins/Experimental/VirtualProductionUtilities/Source/VPUtilities/Private/VPTimecodeCustomTimeStep.cpp:54

Scope (from outer to inner):

file
function     bool UVPTimecodeCustomTimeStep::UpdateTimeStep

Source code excerpt:


	// Loop until we have a new timecode value
	MaxDeltaTime = FMath::Max(0.f, MaxDeltaTime);

	double ActualWaitTime = 0.0;
	bool bSucceed = false;
	FTimecode NewTimecode;
	{
		FSimpleScopeSecondsCounter ActualWaitTimeCounter(ActualWaitTime);

		double BeforeSeconds = FPlatformTime::Seconds();
		while(FPlatformTime::Seconds() - BeforeSeconds < MaxDeltaTime)
		{
			UTimecodeProvider* TimecodeProvider = InEngine->GetTimecodeProvider();

			if (TimecodeProvider == nullptr)
			{
				UE_LOG(LogVPUtilities, Error, TEXT("There is no Timecode Provider for '%s'."), *GetName());

#Loc: <Workspace>/Engine/Plugins/Experimental/VirtualProductionUtilities/Source/VPUtilities/Private/VPTimecodeCustomTimeStep.cpp:124

Scope (from outer to inner):

file
function     bool UVPTimecodeCustomTimeStep::UpdateTimeStep

Source code excerpt:

	if (!bSucceed)
	{
		UE_LOG(LogVPUtilities, Error, TEXT("It took more than %f to update '%s'."), MaxDeltaTime, *GetName());
		State = ECustomTimeStepSynchronizationState::Error;
	}

	return false; // do not execute the engine time step
}

#Loc: <Workspace>/Engine/Plugins/Experimental/VirtualProductionUtilities/Source/VPUtilities/Public/VPTimecodeCustomTimeStep.h:38

Scope (from outer to inner):

file
class        class UVPTimecodeCustomTimeStep : public UFixedFrameRateCustomTimeStep

Source code excerpt:

	/** If the timecode doesn't change after that amount of time, stop the CustomTimeStep. */
	UPROPERTY(EditAnywhere, Category = "CustomTimeStep")
	float MaxDeltaTime = 0.5f;

private:
	bool InitializeFirstStep(UEngine* InEngine);

	void OnTimecodeProviderChanged();

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Classes/NiagaraSystem.h:342

Scope (from outer to inner):

file
class        class UNiagaraSystem : public UFXSystemAsset, public INiagaraParameterDefinitionsSubscriber
function     TOptional<float> GetMaxDeltaTime

Source code excerpt:

	NIAGARA_API const UNiagaraScript* GetSystemUpdateScript() const;

	TOptional<float> GetMaxDeltaTime() const { return MaxDeltaTime; }
	const FNiagaraDataSetAccessor<ENiagaraExecutionState>& GetSystemExecutionStateAccessor() const { return SystemExecutionStateAccessor; }
	TConstArrayView<FNiagaraDataSetAccessor<ENiagaraExecutionState>> GetEmitterExecutionStateAccessors() const { return MakeArrayView(EmitterExecutionStateAccessors); }
	TConstArrayView<FNiagaraDataSetAccessor<FNiagaraSpawnInfo>> GetEmitterSpawnInfoAccessors(int32 EmitterIndex) const { return MakeArrayView(EmitterSpawnInfoAccessors[EmitterIndex]);  }
	
	/** Performs the passed action for all scripts in this system.
	    Include NiagaraSystemImpl.h to be able to call this function */

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Classes/NiagaraSystem.h:995

Scope (from outer to inner):

file
class        class UNiagaraSystem : public UFXSystemAsset, public INiagaraParameterDefinitionsSubscriber

Source code excerpt:

	uint32 bLwcEnabledSettingCached : 1;

	TOptional<float> MaxDeltaTime;
	FNiagaraDataSetAccessor<ENiagaraExecutionState> SystemExecutionStateAccessor;
	TArray<FNiagaraDataSetAccessor<ENiagaraExecutionState>> EmitterExecutionStateAccessors;
	TArray<TArray<FNiagaraDataSetAccessor<FNiagaraSpawnInfo>>> EmitterSpawnInfoAccessors;

	FGraphEventRef ScriptOptimizationCompletionEvent;
	FGraphEventRef PSOPrecacheCompletionEvent;

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraSystem.cpp:2219

Scope (from outer to inner):

file
function     void UNiagaraSystem::CacheFromCompiledData

Source code excerpt:

	EmitterSpawnInfoAccessors.SetNum(GetNumEmitters());

	// reset the MaxDeltaTime so we get the most up to date values from the emitters
	MaxDeltaTime.Reset();

	FGraphEventArray PSOPrecacheEvents;

	TSet<FName> DataInterfaceGpuUsage;
	FNameBuilder ExecutionStateNameBuilder;
	for (int32 i=0; i < EmitterHandles.Num(); ++i)

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraSystem.cpp:2260

Scope (from outer to inner):

file
function     void UNiagaraSystem::CacheFromCompiledData

Source code excerpt:

					if (NiagaraSettings->bLimitDeltaTime)
					{
						MaxDeltaTime = MaxDeltaTime.IsSet() ? FMath::Min(MaxDeltaTime.GetValue(), NiagaraSettings->MaxDeltaTimePerTick) : NiagaraSettings->MaxDeltaTimePerTick;
					}
				}
				EmitterHandle.GetInstance().Emitter->ConditionalPostLoad();
				EmitterData->CacheFromCompiledData(DataSetCompiledData, *EmitterHandle.GetInstance().Emitter);

				PSOPrecacheEvents.Append(EmitterData->PrecacheComputePSOs(*EmitterHandle.GetInstance().Emitter));

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraSystemSimulation.cpp:580

Scope (from outer to inner):

file
function     bool FNiagaraSystemSimulation::Init

Source code excerpt:

	bSystemStateFastPathEnabled = System->SystemStateFastPathEnabled();

	MaxDeltaTime = System->GetMaxDeltaTime();

	if (bCanExecute)
	{
		{
			//SCOPE_CYCLE_COUNTER(STAT_NiagaraSystemSim_Init_DataSets);

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraSystemSimulation.cpp:1132

Scope (from outer to inner):

file
function     void FNiagaraSystemSimulation::Tick_GameThread_Internal

Source code excerpt:

	check(GetSystemInstances(ENiagaraSystemInstanceState::Paused).Num() == PausedDataSet.GetCurrentDataChecked().GetNumInstances());

	if (MaxDeltaTime.IsSet() && !System->HasFixedTickDelta())
	{
		DeltaSeconds = FMath::Clamp(DeltaSeconds, 0.0f, MaxDeltaTime.GetValue());

		TickInfo.SystemTick = DeltaSeconds;
		TickInfo.TimeStepFraction = DeltaSeconds / TickInfo.EngineTick;
	}

	UNiagaraScript* SystemSpawnScript = System->GetSystemSpawnScript();

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraSystemSimulation.cpp:1402

Scope (from outer to inner):

file
function     void FNiagaraSystemSimulation::Spawn_GameThread

Source code excerpt:

	bInSpawnPhase = true;

	if (MaxDeltaTime.IsSet())
	{
		DeltaSeconds = FMath::Clamp(DeltaSeconds, 0.0f, MaxDeltaTime.GetValue());
	}
	if (System->HasFixedTickDelta())
	{
		DeltaSeconds = System->GetFixedTickDeltaTime();
	}

#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Public/NiagaraSystemSimulation.h:417

Scope (from outer to inner):

file
class        class FNiagaraSystemSimulation : public TSharedFromThis<FNiagaraSystemSimulation, ESPMode::ThreadSafe>

Source code excerpt:

	void InitParameterDataSetBindings(FNiagaraSystemInstance* SystemInst);

	TOptional<float> MaxDeltaTime;

	/** Event to track the system simulation async tick is complete. */
	FGraphEventRef ConcurrentTickGraphEvent;
	/** Event to track all work is complete, i.e. System Concurrent, Instance Concurrent, Finalize */
	FGraphEventRef AllWorkCompleteGraphEvent;

#Loc: <Workspace>/Engine/Source/Developer/TraceInsights/Private/Insights/ViewModels/GraphTrack.cpp:952

Scope (from outer to inner):

file
function     void FRandomGraphTrack::GenerateSeries

Source code excerpt:


	constexpr double MinDeltaTime = 0.0000001; // 100ns
	constexpr double MaxDeltaTime = 0.01; // 100ms

	float MinValue = (Seed == 0) ? 0.0f : (Seed == 1) ? -0.25f : -0.5f;
	float MaxValue = (Seed == 0) ? 0.5f : (Seed == 1) ? +0.25f :  0.0f;

	struct FGraphEvent
	{

#Loc: <Workspace>/Engine/Source/Developer/TraceInsights/Private/Insights/ViewModels/GraphTrack.cpp:973

Scope (from outer to inner):

file
function     void FRandomGraphTrack::GenerateSeries

Source code excerpt:

		FGraphEvent Ev;
		Ev.Time = NextT;
		const double TimeAdvance = RandomStream.GetFraction() * (MaxDeltaTime - MinDeltaTime);
		NextT += MinDeltaTime + TimeAdvance;
		Ev.Duration = MinDeltaTime + RandomStream.GetFraction() * TimeAdvance;
		Ev.Value = MinValue + RandomStream.GetFraction() * (MaxValue - MinValue);
		Events.Add(Ev);
	}

#Loc: <Workspace>/Engine/Source/Runtime/AnimGraphRuntime/Private/BoneControllers/AnimNode_AnimDynamics.cpp:403

Scope (from outer to inner):

file
function     void FAnimNode_AnimDynamics::EvaluateSkeletalControl_AnyThread

Source code excerpt:

			{
				// Do variable frame-time update
				const float MaxDeltaTime = MaxPhysicsDeltaTime;

				NextTimeStep = FMath::Min(NextTimeStep, MaxDeltaTime);

				UpdateLimits(Output);
				FAnimPhys::PhysicsUpdate(NextTimeStep, SimBodies, LinearLimits, AngularLimits, Springs, SimSpaceGravityDirection, OrientedExternalForce, ComponentLinearAcc, NumSolverIterationsPreUpdate, NumSolverIterationsPostUpdate);
			}

#if ENABLE_ANIM_DRAW_DEBUG

#Loc: <Workspace>/Engine/Source/Runtime/AnimGraphRuntime/Private/BoneControllers/AnimNode_Trail.cpp:31

Scope (from outer to inner):

file
function     FAnimNode_Trail::FAnimNode_Trail

Source code excerpt:

	, TrailRelaxation_DEPRECATED(10.f)
#endif// #if WITH_EDITORONLY_DATA
	, MaxDeltaTime(0.f)
	, RelaxationSpeedScale(1.f)
	, StretchLimit(0)
	, FakeVelocity(FVector::ZeroVector)
#if WITH_EDITORONLY_DATA
	, TrailBoneRotationBlendAlpha_DEPRECATED(1.f)
#endif // WITH_EDITORONLY_DATA

#Loc: <Workspace>/Engine/Source/Runtime/AnimGraphRuntime/Private/BoneControllers/AnimNode_Trail.cpp:75

Scope (from outer to inner):

file
function     void FAnimNode_Trail::EvaluateSkeletalControl_AnyThread

Source code excerpt:


	check(OutBoneTransforms.Num() == 0);
	const float TimeStep = (MaxDeltaTime > 0.f)? FMath::Clamp(ThisTimstep, 0.f, MaxDeltaTime) : ThisTimstep;
	ThisTimstep = 0.f;

	if( ChainBoneIndices.Num() <= 0 )
	{
		return;
	}

#Loc: <Workspace>/Engine/Source/Runtime/AnimGraphRuntime/Public/BoneControllers/AnimNode_Trail.h:118

Scope: file

Source code excerpt:

#endif // WITH_EDITORONLY_DATA

	/** To avoid hitches causing stretch of trail, you can use MaxDeltaTime to clamp the long delta time. If you want 30 fps to set it to 0.03333f ( = 1/30 ).  */
	UPROPERTY(EditAnywhere, Category = Limit)
	float MaxDeltaTime;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Trail, meta = (PinHiddenByDefault))
	float RelaxationSpeedScale;

	/** How quickly we 'relax' the bones to their animated positions. Time 0 will map to top root joint, time 1 will map to the bottom joint. */
	UPROPERTY(EditAnywhere, Category=Trail, meta=(CustomizeProperty))

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/GameEngine.h:28

Scope (from outer to inner):

file
class        class UGameEngine : public UEngine

Source code excerpt:

	/** Maximium delta time the engine uses to populate FApp::DeltaTime. If 0, unbound. */
	UPROPERTY(config)
	float MaxDeltaTime;

	/** Maximium time (in seconds) between the flushes of the logs on the server (best effort). If 0, this will happen every tick. */
	UPROPERTY(config)
	float ServerFlushLogInterval;

	UPROPERTY(transient)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UnrealEngine.cpp:2724

Scope (from outer to inner):

file
function     void UEngine::UpdateTimeAndHandleMaxTickRate

Source code excerpt:

		// Enforce a maximum delta time if wanted.
		UGameEngine* GameEngine = Cast<UGameEngine>(this);
		const float MaxDeltaTime = GameEngine ? GameEngine->MaxDeltaTime : 0.f;
		if( MaxDeltaTime > 0.f )
		{
			UWorld* World = NULL;

			int32 NumGamePlayers = 0;
			for (int32 WorldIndex = 0; WorldIndex < WorldList.Num(); ++WorldIndex)
			{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UnrealEngine.cpp:2748

Scope (from outer to inner):

file
function     void UEngine::UpdateTimeAndHandleMaxTickRate

Source code excerpt:

			{
				// Happy clamping!
				FApp::SetDeltaTime(FMath::Min<double>(FApp::GetDeltaTime(), MaxDeltaTime));
			}
		}
	}

	bPreviousUseFixedTimeStep = bUseFixedTimeStep;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/PBDRigidsSolver.cpp:510

Scope (from outer to inner):

file
namespace    Chaos
class        class AdvanceOneTimeStepTask : public FNonAbandonableTask
function     void DoWork

Source code excerpt:

				//   energy will be lost.
				const FReal MinDeltaTime = MSolver->GetMinDeltaTime_External();
				const FReal MaxDeltaTime = MSolver->GetMaxDeltaTime_External();
				int32 StepsRemaining = MSubStepInfo.bSolverSubstepped ? 1 : MSolver->GetMaxSubSteps_External();
				FReal TimeRemaining = MDeltaTime;
				bool bFirstStep = true;
				while (StepsRemaining > 0 && TimeRemaining > MinDeltaTime)
				{
					--StepsRemaining;
					const FReal DeltaTime = MaxDeltaTime > 0.f ? FMath::Min(TimeRemaining, MaxDeltaTime) : TimeRemaining;
					TimeRemaining -= DeltaTime;

					{
						MSolver->FieldForcesUpdateCallback();
					}