p.ForceJumpPeakSubstep
p.ForceJumpPeakSubstep
#Overview
name: p.ForceJumpPeakSubstep
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
If 1, force a jump substep to always reach the peak position of a jump, which can often be cut off as framerate lowers.
It is referenced in 5
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of p.ForceJumpPeakSubstep is to ensure that the peak position of a character’s jump is always reached during the physics simulation, even when the framerate is low. This setting is primarily used in the character movement system of Unreal Engine 5.
This setting variable is relied upon by the Character Movement Component, which is part of the Engine module in Unreal Engine 5. It’s specifically used in the physics simulation for falling characters.
The value of this variable is set through a console variable (CVar) named “p.ForceJumpPeakSubstep”. It’s initialized with a default value of 1 (enabled) in the CharacterMovementComponent.cpp file.
The associated variable ForceJumpPeakSubstep interacts directly with p.ForceJumpPeakSubstep. They share the same value, with ForceJumpPeakSubstep being used in the actual code logic.
Developers must be aware that this variable affects the precision of jump simulations. When enabled (set to 1), it forces a sub-step in the physics simulation to ensure the exact peak of a jump is captured. This can be particularly important for gameplay mechanics that rely on precise jump heights or for maintaining consistent behavior across different framerates.
Best practices when using this variable include:
- Keep it enabled (set to 1) for most cases to ensure consistent jump behavior.
- If you’re developing a game with precise platforming elements, this setting is crucial for maintaining fairness and predictability.
- Be aware that forcing this sub-step might have a small performance cost, especially in scenes with many jumping characters.
- When debugging jump-related issues, toggling this setting on and off might help isolate whether the problem is related to the jump peak calculation.
Regarding the associated variable ForceJumpPeakSubstep:
The purpose of ForceJumpPeakSubstep is to serve as the in-code representation of the p.ForceJumpPeakSubstep console variable. It’s used directly in the physics calculations within the Character Movement Component.
This variable is used in the Engine module, specifically within the Character Movement Component’s physics simulation for falling characters.
Its value is set by the console variable system when p.ForceJumpPeakSubstep is modified.
It interacts directly with p.ForceJumpPeakSubstep, effectively mirroring its value.
Developers should be aware that this is the actual variable checked in the code logic. Any runtime changes to p.ForceJumpPeakSubstep will be reflected in this variable.
Best practices for ForceJumpPeakSubstep are the same as for p.ForceJumpPeakSubstep, as they represent the same setting. Developers should generally not modify ForceJumpPeakSubstep directly, but instead use the console variable system to change p.ForceJumpPeakSubstep when needed.
#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:224
Scope (from outer to inner):
file
namespace CharacterMovementCVars
Source code excerpt:
int32 ForceJumpPeakSubstep = 1;
FAutoConsoleVariableRef CVarForceJumpPeakSubstep(
TEXT("p.ForceJumpPeakSubstep"),
ForceJumpPeakSubstep,
TEXT("If 1, force a jump substep to always reach the peak position of a jump, which can often be cut off as framerate lowers."),
ECVF_Default);
static float NetServerMoveTimestampExpiredWarningThreshold = 1.0f;
FAutoConsoleVariableRef CVarNetServerMoveTimestampExpiredWarningThreshold(
#Associated Variable and Callsites
This variable is associated with another variable named ForceJumpPeakSubstep
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/GameFramework/CharacterMovementComponent.h:42
Scope (from outer to inner):
file
namespace CharacterMovementCVars
Source code excerpt:
// Is Async Character Movement enabled?
extern ENGINE_API int32 AsyncCharacterMovement;
extern int32 ForceJumpPeakSubstep;
}
/**
* Tick function that calls UCharacterMovementComponent::PostPhysicsTickComponent
**/
USTRUCT()
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/CharacterMovementComponentAsync.cpp:1040
Scope (from outer to inner):
file
function void FCharacterMovementComponentAsyncInput::PhysFalling
Source code excerpt:
// See if we need to sub-step to exactly reach the apex. This is important for avoiding "cutting off the top" of the trajectory as framerate varies.
if (CharacterMovementCVars::ForceJumpPeakSubstep && OldVelocity.Z > 0.f && Velocity.Z <= 0.f && Output.NumJumpApexAttempts < MaxJumpApexAttemptsPerSimulation)
{
const FVector DerivedAccel = (Velocity - OldVelocity) / timeTick;
if (!FMath::IsNearlyZero(DerivedAccel.Z))
{
const float TimeToApex = -OldVelocity.Z / DerivedAccel.Z;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:222
Scope (from outer to inner):
file
namespace CharacterMovementCVars
Source code excerpt:
ECVF_Default);
int32 ForceJumpPeakSubstep = 1;
FAutoConsoleVariableRef CVarForceJumpPeakSubstep(
TEXT("p.ForceJumpPeakSubstep"),
ForceJumpPeakSubstep,
TEXT("If 1, force a jump substep to always reach the peak position of a jump, which can often be cut off as framerate lowers."),
ECVF_Default);
static float NetServerMoveTimestampExpiredWarningThreshold = 1.0f;
FAutoConsoleVariableRef CVarNetServerMoveTimestampExpiredWarningThreshold(
TEXT("net.NetServerMoveTimestampExpiredWarningThreshold"),
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/CharacterMovementComponent.cpp:4733
Scope (from outer to inner):
file
function void UCharacterMovementComponent::PhysFalling
Source code excerpt:
// See if we need to sub-step to exactly reach the apex. This is important for avoiding "cutting off the top" of the trajectory as framerate varies.
const FVector GravityRelativeOldVelocityWithRootMotion = RotateWorldToGravity(OldVelocityWithRootMotion);
if (CharacterMovementCVars::ForceJumpPeakSubstep && GravityRelativeOldVelocityWithRootMotion.Z > 0.f && RotateWorldToGravity(Velocity).Z <= 0.f && NumJumpApexAttempts < MaxJumpApexAttemptsPerSimulation)
{
const FVector DerivedAccel = (Velocity - OldVelocityWithRootMotion) / timeTick;
const FVector GravityRelativeDerivedAccel = RotateWorldToGravity(DerivedAccel);
if (!FMath::IsNearlyZero(GravityRelativeDerivedAccel.Z))
{
const float TimeToApex = -GravityRelativeOldVelocityWithRootMotion.Z / GravityRelativeDerivedAccel.Z;