AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck

AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck

#Overview

name: AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck

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

It is referenced in 3 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck is to control the number of prediction keys that can be dropped before the StaleKeyBehavior is triggered in the Gameplay Ability System.

This setting variable is primarily used in the Gameplay Abilities plugin, which is part of Unreal Engine’s ability system. It’s specifically related to the prediction and networking aspects of the ability system.

The value of this variable is set through a console variable (CVar) using FAutoConsoleVariableRef. It’s initialized with a default value calculated as FReplicatedPredictionKeyMap::KeyRingBufferSize * NumExpectedLocalPlayers, where NumExpectedLocalPlayers is set to 4.

This variable interacts closely with another variable named CVarStaleKeyBehaviorValue, which determines how to handle stale keys (0 = CaughtUp, 1 = Reject, 2 = Drop).

Developers must be aware that this variable affects the tolerance for dropped prediction keys before the system takes action. Setting it too low might cause unnecessary triggering of the StaleKeyBehavior, while setting it too high might allow too many stale keys to accumulate.

Best practices when using this variable include:

  1. Adjusting it based on the expected number of local players in your game.
  2. Monitoring its impact on network performance and gameplay prediction.
  3. Using it in conjunction with AbilitySystem.PredictionKey.StaleKeyBehavior for fine-tuning the prediction system’s behavior.

Regarding the associated variable CVarMaxStaleKeysBeforeAckValue:

The purpose of CVarMaxStaleKeysBeforeAckValue is to store the actual value used by the MaxStaleKeysBeforeAck setting. It’s an integer variable that directly holds the calculated or set value.

This variable is used within the Gameplay Abilities plugin, specifically in the prediction key handling system.

Its value is set at initialization and can be modified through the console variable system.

CVarMaxStaleKeysBeforeAckValue interacts directly with AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck, serving as its backing storage.

Developers should be aware that modifying CVarMaxStaleKeysBeforeAckValue directly (rather than through the console variable system) might lead to inconsistencies.

Best practices include:

  1. Avoiding direct modification of CVarMaxStaleKeysBeforeAckValue.
  2. Using the console variable system to change the value when necessary.
  3. Considering the implications on network performance and gameplay prediction when adjusting this value.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/GameplayPrediction.cpp:18

Scope (from outer to inner):

file
namespace    UE::AbilitySystem::Private

Source code excerpt:

	constexpr int32 NumExpectedLocalPlayers = 4;
	int32 CVarMaxStaleKeysBeforeAckValue = FReplicatedPredictionKeyMap::KeyRingBufferSize * NumExpectedLocalPlayers;
	FAutoConsoleVariableRef CVarMaxStaleKeysBeforeAck(TEXT("AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck"), CVarMaxStaleKeysBeforeAckValue,
		TEXT("How many prediction keys can be dropped before StaleKeyBehavior is run."));

	// What should we do with these old stale FPredictionKeys?  Prior to UE5.5, we always CaughtUp.  I believe it's actually safer to drop.
	int32 CVarStaleKeyBehaviorValue = 0;
	FAutoConsoleVariableRef CVarStaleKeyBehavior(TEXT("AbilitySystem.PredictionKey.StaleKeyBehavior"), CVarStaleKeyBehaviorValue,
		TEXT("How do we handle stale keys? 0 = CaughtUp. 1 = Reject. 2 = Drop"));

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/GameplayPrediction.cpp:17

Scope (from outer to inner):

file
namespace    UE::AbilitySystem::Private

Source code excerpt:

	// Set it lower to catch bugs related to not sending prediction keys sooner in your logs, or higher if you have a massive local player count.
	constexpr int32 NumExpectedLocalPlayers = 4;
	int32 CVarMaxStaleKeysBeforeAckValue = FReplicatedPredictionKeyMap::KeyRingBufferSize * NumExpectedLocalPlayers;
	FAutoConsoleVariableRef CVarMaxStaleKeysBeforeAck(TEXT("AbilitySystem.PredictionKey.MaxStaleKeysBeforeAck"), CVarMaxStaleKeysBeforeAckValue,
		TEXT("How many prediction keys can be dropped before StaleKeyBehavior is run."));

	// What should we do with these old stale FPredictionKeys?  Prior to UE5.5, we always CaughtUp.  I believe it's actually safer to drop.
	int32 CVarStaleKeyBehaviorValue = 0;
	FAutoConsoleVariableRef CVarStaleKeyBehavior(TEXT("AbilitySystem.PredictionKey.StaleKeyBehavior"), CVarStaleKeyBehaviorValue,
		TEXT("How do we handle stale keys? 0 = CaughtUp. 1 = Reject. 2 = Drop"));

#Loc: <Workspace>/Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/GameplayPrediction.cpp:550

Scope (from outer to inner):

file
function     void FReplicatedPredictionKeyItem::OnRep

Source code excerpt:

	// and one way that can happen, is if no FPredictionKeys in a dependency chain are sent to the server.  In such a case, you've locally predicted
	// a bunch of events that the server has no way of accepting/rejecting.  A decision was made long ago to auto-accept these, so let's keep that functionality.
	const int MaxKeyLagValue = FMath::Max(CVarMaxStaleKeysBeforeAckValue, FReplicatedPredictionKeyMap::KeyRingBufferSize);

	// We now define a range from [Min,Max] but since it's a circular buffer, it can also be [0,Min] [Max,KeyMax]
	constexpr int32 MaxKeyValue = std::numeric_limits<FPredictionKey::KeyType>::max();
	int32 RangeMin = (PredictionKey.Current - MaxKeyLagValue) > 0 ? (PredictionKey.Current - MaxKeyLagValue) : MaxKeyValue + (PredictionKey.Current - MaxKeyLagValue);
	int32 RangeMax = (PredictionKey.Current + MaxKeyLagValue) % MaxKeyValue;