p.NetUseClientTimestampForReplicatedTransform

p.NetUseClientTimestampForReplicatedTransform

#Overview

name: p.NetUseClientTimestampForReplicatedTransform

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

It is referenced in 4 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of p.NetUseClientTimestampForReplicatedTransform is to control how timestamps are handled for replicated character transforms in networked gameplay. This setting is primarily used in the character movement system of Unreal Engine 5.

This setting variable is relied upon by the Engine module, specifically within the CharacterMovementComponent. It affects how the game handles network synchronization for character movement.

The value of this variable is set through a console variable (CVar) system. It’s initialized to 1 (enabled) by default, but can be changed at runtime through console commands or configuration files.

The associated variable NetUseClientTimestampForReplicatedTransform directly interacts with p.NetUseClientTimestampForReplicatedTransform. They share the same value and purpose.

Developers must be aware that changing this variable at runtime usually requires a game session restart to take effect fully. This is because it fundamentally changes how network synchronization works for character movement.

Best practices when using this variable include:

  1. Carefully consider the implications on network performance and gameplay before changing it.
  2. Test thoroughly in networked environments to ensure desired behavior.
  3. Document any changes to this setting in your project, as it can significantly affect multiplayer gameplay.

Regarding the associated variable NetUseClientTimestampForReplicatedTransform:

Its purpose is identical to p.NetUseClientTimestampForReplicatedTransform. It’s used within the character movement system to determine whether to use client-provided timestamps or server-generated timestamps for replicated character transforms.

This variable is used in the CharacterMovementComponent and CharacterMovementComponentAsync systems. It’s checked during the PerformMovement function to decide how to set the ServerLastTransformUpdateTimeStamp.

The value is set through the console variable system, mirroring p.NetUseClientTimestampForReplicatedTransform.

When this variable is enabled (set to 1), the system uses the client’s timestamp for replicated transforms. When disabled (set to 0), it uses the server’s tick time instead.

Developers should be aware that this setting can significantly impact how character movement is synchronized in multiplayer games. It’s a trade-off between using potentially more accurate client timing and trusting the server’s timing.

Best practices include thorough testing in various network conditions and considering the implications on anti-cheat systems when allowing client timestamps to be used.

#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:200

Scope (from outer to inner):

file
namespace    CharacterMovementCVars

Source code excerpt:

	static int32 NetUseClientTimestampForReplicatedTransform = 1;
	FAutoConsoleVariableRef CVarNetUseClientTimestampForReplicatedTransform(
		TEXT("p.NetUseClientTimestampForReplicatedTransform"),
		NetUseClientTimestampForReplicatedTransform,
		TEXT("If enabled, use client timestamp changes to track the replicated transform timestamp, otherwise uses server tick time as the timestamp.\n")
		TEXT("Game session usually needs to be restarted if this is changed at runtime.\n")
		TEXT("0: Disable, 1: Enable"),
		ECVF_Default);

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/CharacterMovementComponentAsync.cpp:447

Scope (from outer to inner):

file
function     void FCharacterMovementComponentAsyncInput::PerformMovement

Source code excerpt:

			const bool bIsRemotePlayer = (CharacterOwner->GetRemoteRole() == ROLE_AutonomousProxy);
			const FNetworkPredictionData_Server_Character* ServerData = bIsRemotePlayer ? GetPredictionData_Server_Character() : nullptr;
			if (bIsRemotePlayer && ServerData && CharacterMovementCVars::NetUseClientTimestampForReplicatedTransform)
			{
				ServerLastTransformUpdateTimeStamp = float(ServerData->ServerAccumulatedClientTimeStamp);
			}
			else
			{
				ServerLastTransformUpdateTimeStamp = MyWorld->GetTimeSeconds();
			}
		}
	}*/

	Output.LastUpdateLocation = NewLocation;
	Output.LastUpdateRotation = NewRotation;
	Output.LastUpdateVelocity = Velocity;
}

void FCharacterMovementComponentAsyncInput::MaybeUpdateBasedMovement(float DeltaSeconds, FCharacterMovementComponentAsyncOutput& Output) const
{
	bool& bDeferUpdateBasedMovement = Output.bDeferUpdateBasedMovement;

	MovementBaseAsyncData.Validate(Output);
	const bool& bMovementBaseUsesRelativeLocation = MovementBaseAsyncData.bMovementBaseUsesRelativeLocationCached;
	const bool& bMovementBaseIsSimulated = MovementBaseAsyncData.bMovementBaseIsSimulatedCached;

	bDeferUpdateBasedMovement = false;

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

Scope (from outer to inner):

file
namespace    CharacterMovementCVars

Source code excerpt:

		ECVF_Default);

	static int32 NetUseClientTimestampForReplicatedTransform = 1;
	FAutoConsoleVariableRef CVarNetUseClientTimestampForReplicatedTransform(
		TEXT("p.NetUseClientTimestampForReplicatedTransform"),
		NetUseClientTimestampForReplicatedTransform,
		TEXT("If enabled, use client timestamp changes to track the replicated transform timestamp, otherwise uses server tick time as the timestamp.\n")
		TEXT("Game session usually needs to be restarted if this is changed at runtime.\n")
		TEXT("0: Disable, 1: Enable"),
		ECVF_Default);

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

Scope (from outer to inner):

file
function     void UCharacterMovementComponent::PerformMovement

Source code excerpt:

			const bool bIsRemotePlayer = (CharacterOwner->GetRemoteRole() == ROLE_AutonomousProxy);
			const FNetworkPredictionData_Server_Character* ServerData = bIsRemotePlayer ? GetPredictionData_Server_Character() : nullptr;
			if (bIsRemotePlayer && ServerData && CharacterMovementCVars::NetUseClientTimestampForReplicatedTransform)
			{
				ServerLastTransformUpdateTimeStamp = float(ServerData->ServerAccumulatedClientTimeStamp);
			}
			else
			{
				ServerLastTransformUpdateTimeStamp = MyWorld->GetTimeSeconds();