p.NetCorrectionLifetime

p.NetCorrectionLifetime

#Overview

name: p.NetCorrectionLifetime

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

It is referenced in 10 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of p.NetCorrectionLifetime is to control the duration of visualized network corrections in Unreal Engine’s character movement and physics replication systems. It is primarily used for debugging and visualization purposes.

This setting variable is utilized by the following Unreal Engine subsystems and modules:

  1. Character Movement Component
  2. Physics Replication System

The value of this variable is set using an FAutoConsoleVariableRef in the CharacterMovementCVars namespace. It is initialized with a default value of 4.0 seconds.

The associated variable NetCorrectionLifetime interacts directly with p.NetCorrectionLifetime, sharing the same value. This variable is used throughout the code to determine the lifetime of debug visualizations.

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

  1. It is only active in non-shipping builds (DEBUG or DEVELOPMENT).
  2. It affects the duration of debug visualizations for network corrections, which can be useful for identifying and diagnosing network-related movement issues.
  3. Changing this value will impact the visibility duration of debug drawings in the game world.

Best practices when using this variable include:

  1. Adjust the value as needed during development to better visualize and debug network corrections.
  2. Keep in mind that longer durations may clutter the debug visualization, while shorter durations might make it harder to spot issues.
  3. Use in conjunction with other debugging tools and console variables to get a comprehensive view of character movement and physics replication behavior.

Regarding the associated variable NetCorrectionLifetime:

The purpose of NetCorrectionLifetime is to provide a convenient way to access the p.NetCorrectionLifetime value within the code. It is used in various functions to set the lifetime of debug drawings and visualizations related to network corrections.

This variable is used in multiple locations within the CharacterMovementComponent and PhysicsReplication systems to control the duration of debug visualizations. It directly reflects the value set by p.NetCorrectionLifetime.

Developers should be aware that changes to p.NetCorrectionLifetime will affect all uses of NetCorrectionLifetime throughout the code. When working with this variable, ensure that the visualizations remain useful for debugging purposes without becoming overly intrusive or persistent.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:344

Scope (from outer to inner):

file
namespace    CharacterMovementCVars

Source code excerpt:

	float NetCorrectionLifetime = 4.f;
	FAutoConsoleVariableRef CVarNetCorrectionLifetime(
		TEXT("p.NetCorrectionLifetime"),
		NetCorrectionLifetime,
		TEXT("How long a visualized network correction persists.\n")
		TEXT("Time in seconds each visualized network correction persists."),
		ECVF_Cheat);

#endif // !UE_BUILD_SHIPPING

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:342

Scope (from outer to inner):

file
namespace    CharacterMovementCVars

Source code excerpt:

		ECVF_Cheat);

	float NetCorrectionLifetime = 4.f;
	FAutoConsoleVariableRef CVarNetCorrectionLifetime(
		TEXT("p.NetCorrectionLifetime"),
		NetCorrectionLifetime,
		TEXT("How long a visualized network correction persists.\n")
		TEXT("Time in seconds each visualized network correction persists."),
		ECVF_Cheat);

#endif // !UE_BUILD_SHIPPING

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10020

Scope (from outer to inner):

file
function     void UCharacterMovementComponent::ServerMoveHandleClientError

Source code excerpt:

			UE_LOG(LogNetPlayerMovement, Warning, TEXT("*** Server: Error for %s at Time=%.3f is %3.3f LocDiff(%s) ClientLoc(%s) ServerLoc(%s) Base: %s Bone: %s Accel(%s) Velocity(%s)"),
				*GetNameSafe(CharacterOwner), ClientTimeStamp, LocDiff.Size(), *LocDiff.ToString(), *ClientLoc.ToString(), *UpdatedComponent->GetComponentLocation().ToString(), *BaseString, *ServerData->PendingAdjustment.NewBaseBoneName.ToString(), *Accel.ToString(), *Velocity.ToString());
			const float DebugLifetime = CharacterMovementCVars::NetCorrectionLifetime;
			DrawDebugCapsule(GetWorld(), UpdatedComponent->GetComponentLocation(), CharacterOwner->GetSimpleCollisionHalfHeight(), CharacterOwner->GetSimpleCollisionRadius(), FQuat::Identity, FColor(100, 255, 100), false, DebugLifetime);
			DrawDebugCapsule(GetWorld(), ClientLoc                    , CharacterOwner->GetSimpleCollisionHalfHeight(), CharacterOwner->GetSimpleCollisionRadius(), FQuat::Identity, FColor(255, 100, 100), false, DebugLifetime);
		}
#endif

		ServerData->LastUpdateTime = GetWorld()->TimeSeconds;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:10896

Scope (from outer to inner):

file
function     void UCharacterMovementComponent::OnClientCorrectionReceived

Source code excerpt:

		UE_LOG(LogNetPlayerMovement, Warning, TEXT("*** Client: Error for %s at Time=%.3f is %3.3f LocDiff(%s) ClientLoc(%s) ServerLoc(%s) NewBase: %s NewBone: %s ClientVel(%s) ServerVel(%s) SavedMoves %d"),
			   *GetNameSafe(CharacterOwner), TimeStamp, LocDiff.Size(), *LocDiff.ToString(), *ClientLocAtCorrectedMove.ToString(), *NewLocation.ToString(), *NewBaseString, *NewBaseBoneName.ToString(), *Velocity.ToString(), *NewVelocity.ToString(), ClientData.SavedMoves.Num());
		const float DebugLifetime = CharacterMovementCVars::NetCorrectionLifetime;
		if (!LocDiff.IsNearlyZero())
		{
			// When server corrects us to a new location, draw red at location where client thought they were, green where the server corrected us to
			DrawDebugCapsule(GetWorld(), ClientLocAtCorrectedMove, CharacterOwner->GetSimpleCollisionHalfHeight(), CharacterOwner->GetSimpleCollisionRadius(), FQuat::Identity, FColor(255, 100, 100), false, DebugLifetime);
			DrawDebugCapsule(GetWorld(), NewLocation, CharacterOwner->GetSimpleCollisionHalfHeight(), CharacterOwner->GetSimpleCollisionRadius(), FQuat::Identity, FColor(100, 255, 100), false, DebugLifetime);
		}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysicsReplication.cpp:21

Scope (from outer to inner):

file
namespace    CharacterMovementCVars

Source code excerpt:

{
	extern int32 NetShowCorrections;
	extern float NetCorrectionLifetime;

	int32 SkipPhysicsReplication = 0;
	static FAutoConsoleVariableRef CVarSkipPhysicsReplication(TEXT("p.SkipPhysicsReplication"), SkipPhysicsReplication, TEXT(""));

	float NetPingExtrapolation = -1.0f;
	static FAutoConsoleVariableRef CVarNetPingExtrapolation(TEXT("p.NetPingExtrapolation"), NetPingExtrapolation, TEXT(""));

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysicsReplication.cpp:724

Scope (from outer to inner):

file
function     bool FPhysicsReplication::ApplyRigidBodyState

Source code excerpt:

			{
				FColor Color = FColor::White;
				DrawDebugDirectionalArrow(OwningWorld, CurrentState.Position, TargetPos, 5.0f, Color, true, CharacterMovementCVars::NetCorrectionLifetime, 0, 1.5f);
				DrawDebugFloatHistory(*OwningWorld, PhysicsTarget.ErrorHistory, CurrentState.Position + FVector(0.0f, 0.0f, 100.0f), FVector2D(100.0f, 50.0f), FColor::White, false, 0, -1);
			}
		}
#endif
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysicsReplication.cpp:989

Scope (from outer to inner):

file
function     void FPhysicsReplicationAsync::UpdateAsyncTarget

Source code excerpt:

			{
				const FVector Offset = FVector(0.0f, 0.0f, 50.0f);
				Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Input.TargetState.Position + Offset, FVector(15.0f, 15.0f, 15.0f), Input.TargetState.Quaternion, FColor::MakeRandomSeededColor(Input.ServerFrame), false, CharacterMovementCVars::NetCorrectionLifetime, 0, 1.0f);
			}
#endif

			// Cache the position we received this target at, Predictive Interpolation will alter the target state but use this as the source position for reconciliation.
			Target->PrevPosTarget = Input.TargetState.Position;
			Target->PrevRotTarget = Input.TargetState.Quaternion;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysicsReplication.cpp:1463

Scope (from outer to inner):

file
function     bool FPhysicsReplicationAsync::PredictiveInterpolation

Source code excerpt:

		const FVector StartPos = Target.TargetState.Position + Offset;
		const int32 SizeMultiplier = FMath::Clamp(Target.TickCount, -4, 30);
		Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(StartPos, FVector(5.0f + SizeMultiplier * 0.75f, 5.0f + SizeMultiplier * 0.75f, 5.0f + SizeMultiplier * 0.75f), Target.TargetState.Quaternion, FColor::MakeRandomSeededColor(Target.ServerFrame), false, CharacterMovementCVars::NetCorrectionLifetime, 0, 1.0f);
	}
#endif

	const bool bIsSleeping = Handle->IsSleeping();
	const bool bCanSimulate = Handle->IsDynamic() || bIsSleeping;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysicsReplication.cpp:1817

Scope (from outer to inner):

file
function     bool FPhysicsReplicationAsync::ResimulationReplication

Source code excerpt:

		const FColor DebugColor = FLinearColor::LerpUsingHSV(FLinearColor::Green, FLinearColor::Red, ColorLerp).ToFColor(false);

		Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Target.TargetState.Position, FVector(BoxSize, BoxSize, BoxSize), Target.TargetState.Quaternion, FColor::Orange, true, CharacterMovementCVars::NetCorrectionLifetime, 0, 1.0f);
		Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(PastState.GetX(), FVector(6, 6, 6), PastState.GetR(), DebugColor, true, CharacterMovementCVars::NetCorrectionLifetime, 0, 1.0f);

		Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(PastState.GetX(), Target.TargetState.Position, 5.0f, FColor::MakeRandomSeededColor(LocalFrame), true, CharacterMovementCVars::NetCorrectionLifetime, 0, 0.5f);
	}
#endif

	if (LocalFrame > RewindData->GetBlockedResimFrame())
	{
		if (ShouldTriggerResim && Target.TickCount == 0)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysicsReplication.cpp:1874

Scope (from outer to inner):

file
function     bool FPhysicsReplicationAsync::ResimulationReplication

Source code excerpt:

				if (PhysicsReplicationCVars::ResimulationCVars::bDrawDebug)
				{
					Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Handle->GetX(), CorrectedX, 5.0f, FColor::MakeRandomSeededColor(LocalFrame), true, CharacterMovementCVars::NetCorrectionLifetime, 0, 0.5f);
				}
#endif
				// Apply correction to position and rotation
				RigidsSolver->GetEvolution()->ApplyParticleTransformCorrection(Handle, CorrectedX, CorrectedR, PhysicsReplicationCVars::ResimulationCVars::bRuntimeCorrectConnectedBodies);
			}