A technical deep dive into extending Unreal Engine 5’s movement physics, managing engine crashes, and solving complex vector math problems.
UCharacterMovementComponent
to remain compatible with Unreal’s movement pipeline and
future networking support.
The following chart visualizes the decision-making inside
TryEnterWallRun() and the custom physics update
loop.
The hardest part wasn’t wall detection, it was making the movement feel physically correct without instant sliding or unnatural sticking.
The Gravity Issue: Disabling gravity felt floaty. Using default gravity caused the player to drop too aggressively.
The Solution: A Dynamic Gravity Ramp. Gravity starts reduced on wall contact, then ramps up over time, naturally forcing the player to jump off or fall.
// Ramp gravity over time to maintain weight and control
float GravityFactor =
FMath::Clamp(CurrentWallRunTime / GravityRampDuration, 0.f, 1.f);
// Apply gravity relative to time spent on wall
Velocity.Z += (BaseGravity + GravityRamp * GravityFactor) * DeltaTime;
// Prevent instant plummeting
Velocity.Z = FMath::Clamp(Velocity.Z, -600.f, 200.f);
Extending UCharacterMovementComponent is
powerful but dangerous.
Early versions caused multiple crashes related to
SafeMoveUpdatedComponent.
Directly modifying velocity inside PhysCustom
without properly resolving
blocking hits caused the capsule to become embedded in
geometry,
leading to physics instability and division-by-zero errors.
The Fix: All movement was rewritten to rely
on
FVector::VectorPlaneProject, ensuring velocity
is safely projected
along the wall surface before movement is
committed.
PhysFalling) to understand
sub-stepping, collision, and movement constraints.DrawDebugHelpers to visualize normals,
traces, and velocity vectors in real time.The result is a stable, physics-driven wall-run system with predictable entry, sustained momentum, and clean exit behavior, without teleportation or animation dependency.