diff --git a/Source/TengriPlatformer/Movement/Collision/TengriCollisionResolver.cpp b/Source/TengriPlatformer/Movement/Collision/TengriCollisionResolver.cpp index e61a44c..1b63598 100644 --- a/Source/TengriPlatformer/Movement/Collision/TengriCollisionResolver.cpp +++ b/Source/TengriPlatformer/Movement/Collision/TengriCollisionResolver.cpp @@ -175,8 +175,7 @@ bool UTengriCollisionResolver::StepUp( } // Validate actual height difference - const float RealHeightDiff = DownSweep.Location.Z - StartLocation.Z; - if (RealHeightDiff > (MaxStepHeight + TengriPhysics::StepHeightTolerance)) + if (const float RealHeightDiff = DownSweep.Location.Z - StartLocation.Z; RealHeightDiff > (MaxStepHeight + TengriPhysics::StepHeightTolerance)) { return false; } @@ -269,13 +268,17 @@ namespace return HorizontalTangent * FVector::DotProduct(RemainingDelta, HorizontalTangent); } - /** Calculate slide along wall, preventing upward velocity from steep surfaces */ + /** + * Calculate slide along wall, preventing upward velocity for grounded movement. + * When jumping (RemainingDelta.Z > 0), allow sliding upward along walls. + * When grounded (RemainingDelta.Z <= 0), force horizontal movement only. + */ FVector CalculateWallSlide(const FVector& RemainingDelta, const FVector& ImpactNormal) { FVector ClipDelta = UTengriCollisionResolver::ClipVelocity(RemainingDelta, ImpactNormal); - // If wall would push us up, force horizontal movement only - if (ClipDelta.Z > 0.f) + // Allow upward wall slide during jumps, prevent it when grounded + if (const bool bWasJumping = RemainingDelta.Z > TengriPhysics::MinUpwardVelocity; ClipDelta.Z > 0.f && !bWasJumping) { if (FVector HorizontalTangent = FVector::CrossProduct(ImpactNormal, FVector(0.f, 0.f, 1.f)).GetSafeNormal(); !HorizontalTangent.IsNearlyZero()) { @@ -346,6 +349,12 @@ FTengriSweepResult UTengriCollisionResolver::ResolveMovement( FinalResult.bBlocked = true; FinalResult.Hit = Sweep.Hit; + // Scale remaining delta by unfinished movement + if (Sweep.Hit.Time < 1.0f) + { + RemainingDelta *= (1.0f - Sweep.Hit.Time); + } + // Classify surface const float NormalZ = Sweep.Hit.ImpactNormal.Z; const bool bIsFloor = Thresholds.IsWalkable(NormalZ);