Fix air spline locomotion and flat spline

This commit is contained in:
Maxime Maurin 2023-11-22 22:59:30 +01:00
parent 75c325c4cc
commit 29fd695a03
10 changed files with 60 additions and 25 deletions

Binary file not shown.

Binary file not shown.

View File

@ -48,8 +48,7 @@ void UPwnCharacterMovementComponent::OnMovementModeChanged(EMovementMode Previou
Super::OnMovementModeChanged(PreviousMovementMode, PreviousCustomMode); Super::OnMovementModeChanged(PreviousMovementMode, PreviousCustomMode);
// React to changes in the movement mode. // React to changes in the movement mode.
if (MovementMode == MOVE_Custom && CustomMovementMode == SplineWalking) if (MovementMode == MOVE_Custom && CustomMovementMode == SplineWalking) {
{
// make sure we update our new floor/base on initial entry of the walking physics // make sure we update our new floor/base on initial entry of the walking physics
FindFloor(UpdatedComponent->GetComponentLocation(), CurrentFloor, false); FindFloor(UpdatedComponent->GetComponentLocation(), CurrentFloor, false);
AdjustFloorHeight(); AdjustFloorHeight();
@ -112,7 +111,7 @@ bool UPwnCharacterMovementComponent::IsCustomMovementMode(const ECustomMovementM
void UPwnCharacterMovementComponent::RecomputeTangentAndAcceleration() { void UPwnCharacterMovementComponent::RecomputeTangentAndAcceleration() {
Tangent2D = CombatPath->Spline->GetTangentAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World).GetSafeNormal2D(); Tangent2D = CombatPath->Spline->GetTangentAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World).GetSafeNormal2D();
// Recalculate acceleration so the input is relative to the spline // Recalculate acceleration so the input is relative to the spline
Acceleration = Tangent2D * Acceleration.Size2D() * FMath::Sign(Acceleration.X); Acceleration = Tangent2D * Acceleration.Size2D() * FMath::Sign(Acceleration.X) * DotDirection;
} }
void UPwnCharacterMovementComponent::UpdatePawnVelocity(const float TimeTick) { void UPwnCharacterMovementComponent::UpdatePawnVelocity(const float TimeTick) {
@ -140,10 +139,23 @@ void UPwnCharacterMovementComponent::UpdatePawnVelocity(const float TimeTick) {
DistanceAlongSpline = NewDistanceAlongSpline; DistanceAlongSpline = NewDistanceAlongSpline;
} }
void UPwnCharacterMovementComponent::UpdateDistanceAlongSpline() { void UPwnCharacterMovementComponent::UpdateDistanceAlongSplineAndLocation() {
// Maintain coherent distance along spline with location // Maintain coherent distance along spline with location
const float InputKey = CombatPath->Spline->FindInputKeyClosestToWorldLocation(UpdatedComponent->GetComponentLocation()); FHitResult Hit;
DistanceAlongSpline = CombatPath->Spline->GetDistanceAlongSplineAtSplineInputKey(InputKey); FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(GetOwner());
if (GetWorld()->LineTraceSingleByChannel(Hit, UpdatedComponent->GetComponentLocation(),
UpdatedComponent->GetComponentLocation() + FVector(0.0f, 0.0f, -10000.0f),
ECC_Visibility, QueryParams)) {
FVector ImpactPoint = Hit.ImpactPoint;
const float InputKey = CombatPath->Spline->FindInputKeyClosestToWorldLocation(ImpactPoint);
DistanceAlongSpline = CombatPath->Spline->GetDistanceAlongSplineAtSplineInputKey(InputKey);
}
FVector TargetLocation = CombatPath->Spline->GetLocationAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World);
TargetLocation.Z = UpdatedComponent->GetComponentLocation().Z;
UpdatedComponent->SetWorldLocation(TargetLocation);
} }
void UPwnCharacterMovementComponent::PhysSplineWalking(const float DeltaTime, int32 Iterations) { void UPwnCharacterMovementComponent::PhysSplineWalking(const float DeltaTime, int32 Iterations) {
@ -183,15 +195,15 @@ void UPwnCharacterMovementComponent::PhysSplineWalking(const float DeltaTime, in
const FVector OldLocation = UpdatedComponent->GetComponentLocation(); const FVector OldLocation = UpdatedComponent->GetComponentLocation();
const FFindFloorResult OldFloor = CurrentFloor; const FFindFloorResult OldFloor = CurrentFloor;
RecomputeTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */
Acceleration.Z = 0.f;
RestorePreAdditiveRootMotionVelocity(); RestorePreAdditiveRootMotionVelocity();
// Ensure velocity is horizontal. // Ensure velocity is horizontal.
MaintainHorizontalGroundVelocity(); MaintainHorizontalGroundVelocity();
const FVector OldVelocity = Velocity; const FVector OldVelocity = Velocity;
RecomputeTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */
Acceleration.Z = 0.f;
// Apply acceleration // Apply acceleration
if (!HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity()) { if (!HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity()) {
CalcVelocity(TimeTick, GroundFriction, false, GetMaxBrakingDeceleration()); CalcVelocity(TimeTick, GroundFriction, false, GetMaxBrakingDeceleration());
@ -343,7 +355,7 @@ void UPwnCharacterMovementComponent::PhysSplineWalking(const float DeltaTime, in
MaintainHorizontalGroundVelocity(); MaintainHorizontalGroundVelocity();
} }
UpdateDistanceAlongSpline(); /* -- PAWN MODIFICATIONS -- */ UpdateDistanceAlongSplineAndLocation(); /* -- PAWN MODIFICATIONS -- */
} }
UE_DISABLE_OPTIMIZATION UE_DISABLE_OPTIMIZATION
@ -353,6 +365,8 @@ void UPwnCharacterMovementComponent::PhysSplineFalling(const float DeltaTime, in
return; return;
} }
RecomputeTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */
FVector FallAcceleration = GetFallingLateralAcceleration(DeltaTime); FVector FallAcceleration = GetFallingLateralAcceleration(DeltaTime);
FallAcceleration.Z = 0.f; FallAcceleration.Z = 0.f;
const bool bHasLimitedAirControl = ShouldLimitAirControl(DeltaTime, FallAcceleration); const bool bHasLimitedAirControl = ShouldLimitAirControl(DeltaTime, FallAcceleration);
@ -367,8 +381,6 @@ void UPwnCharacterMovementComponent::PhysSplineFalling(const float DeltaTime, in
const FQuat PawnRotation = UpdatedComponent->GetComponentQuat(); const FQuat PawnRotation = UpdatedComponent->GetComponentQuat();
bJustTeleported = false; bJustTeleported = false;
RecomputeTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */
const FVector OldVelocityWithRootMotion = Velocity; const FVector OldVelocityWithRootMotion = Velocity;
RestorePreAdditiveRootMotionVelocity(); RestorePreAdditiveRootMotionVelocity();
@ -657,7 +669,7 @@ void UPwnCharacterMovementComponent::PhysSplineFalling(const float DeltaTime, in
} }
} }
UpdateDistanceAlongSpline(); /* -- PAWN MODIFICATIONS -- */ UpdateDistanceAlongSplineAndLocation(); /* -- PAWN MODIFICATIONS -- */
} }
UE_ENABLE_OPTIMIZATION UE_ENABLE_OPTIMIZATION

View File

@ -19,6 +19,26 @@ void APwnCombatPlatformerPath::BeginPlay() {
UPwnGameplayModeSubsystem* Subsystem = GetWorld()->GetSubsystem<UPwnGameplayModeSubsystem>(); UPwnGameplayModeSubsystem* Subsystem = GetWorld()->GetSubsystem<UPwnGameplayModeSubsystem>();
check(Subsystem); check(Subsystem);
Subsystem->RegisterCombatPath(this); Subsystem->RegisterCombatPath(this);
const FVector FirstPointLocation = Spline->GetLocationAtSplinePoint(0, ESplineCoordinateSpace::World);
float FirstPointZ = FirstPointLocation.Z;
const int32 PointsCount = Spline->GetNumberOfSplinePoints();
for (int i = 0; i < PointsCount; ++i) {
FVector NewLocation = Spline->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::World);
NewLocation.Z = FirstPointZ;
Spline->SetLocationAtSplinePoint(i, NewLocation, ESplineCoordinateSpace::World, false);
FVector ArriveTangent = Spline->GetArriveTangentAtSplinePoint(i, ESplineCoordinateSpace::World);
FVector LeaveTangent = Spline->GetLeaveTangentAtSplinePoint(i, ESplineCoordinateSpace::World);
ArriveTangent.Z = 0;
LeaveTangent.Z = 0;
Spline->SetTangentsAtSplinePoint(i, ArriveTangent, LeaveTangent, ESplineCoordinateSpace::World, false);
}
Spline->UpdateSpline();
Super::BeginPlay(); Super::BeginPlay();
} }

View File

@ -52,7 +52,7 @@ private:
void UpdatePawnVelocity(const float TimeTick); void UpdatePawnVelocity(const float TimeTick);
void UpdateDistanceAlongSpline(); void UpdateDistanceAlongSplineAndLocation();
void PhysSplineWalking(const float DeltaTime, int32 Iterations); void PhysSplineWalking(const float DeltaTime, int32 Iterations);