diff --git a/Pawn_Unreal/Content/Characters/BP_Judy.uasset b/Pawn_Unreal/Content/Characters/BP_Judy.uasset index 02f283d..81daf98 100644 --- a/Pawn_Unreal/Content/Characters/BP_Judy.uasset +++ b/Pawn_Unreal/Content/Characters/BP_Judy.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6881e0fd1cf9f28c1d39877ffaac2336180b96da284f3fe3bb27e083b0fa36f -size 217961 +oid sha256:ba68b8e6df108b46ff6182f4bb3a15391034b9259b8e16381379bd711afb5e04 +size 217117 diff --git a/Pawn_Unreal/Content/Systems/Camera/BP_MainCameraManager.uasset b/Pawn_Unreal/Content/Systems/Camera/BP_MainCameraManager.uasset index c435b3f..8c0ab71 100644 --- a/Pawn_Unreal/Content/Systems/Camera/BP_MainCameraManager.uasset +++ b/Pawn_Unreal/Content/Systems/Camera/BP_MainCameraManager.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:155a440d5b0eb481008779e3cbbdc57674746b453d91f0094b7066f2d04623da -size 382332 +oid sha256:7b6bc522ab4664b5a68e5e9661850906c9fb33725a3a60f194b7c3488c5138a3 +size 382307 diff --git a/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp index 8243271..7580329 100644 --- a/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp +++ b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp @@ -7,6 +7,8 @@ #include "GameplayModes/Combat/PwnCombatPlatformerPath.h" #include "Utils/EngineUtils.h" +constexpr float LineTraceDistance = 10000.0f; + UPwnCharacterMovementComponent::UPwnCharacterMovementComponent() { PrimaryComponentTick.bCanEverTick = true; } @@ -45,19 +47,19 @@ bool UPwnCharacterMovementComponent::IsFalling() const { return Super::IsFalling() || IsCustomMovementMode(SplineFalling); } -void UPwnCharacterMovementComponent::OnMovementModeChanged(EMovementMode PreviousMovementMode, uint8 PreviousCustomMode) { +void UPwnCharacterMovementComponent::OnMovementModeChanged(const EMovementMode PreviousMovementMode, const uint8 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) { - // 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); AdjustFloorHeight(); SetBaseFromFloor(CurrentFloor); } } -void UPwnCharacterMovementComponent::UpdateCharacterStateBeforeMovement(float DeltaSeconds) { +void UPwnCharacterMovementComponent::UpdateCharacterStateBeforeMovement(const float DeltaSeconds) { if (MovementMode == MOVE_Falling && IsFollowingSpline) { SetMovementMode(MOVE_Custom, SplineFalling); } else if (MovementMode == MOVE_Walking && IsFollowingSpline) { @@ -93,14 +95,14 @@ void UPwnCharacterMovementComponent::EnterSplineFollowMode() { CombatPath = OutCombatPath; DotDirection = CombatPath->Reversed ? -1.0f : 1.0f; - float ClosestInputKey = CombatPath->Spline->FindInputKeyClosestToWorldLocation(UpdatedComponent->GetComponentLocation()); + const float ClosestInputKey = CombatPath->Spline->FindInputKeyClosestToWorldLocation(UpdatedComponent->GetComponentLocation()); FVector ClosestLocation = CombatPath->Spline->GetLocationAtSplineInputKey(ClosestInputKey, ESplineCoordinateSpace::World); FHitResult Hit; - if (GetWorld()->LineTraceSingleByChannel(Hit, ClosestLocation, ClosestLocation + FVector(0.0f, 0.0f, -10000.0f), + if (GetWorld()->LineTraceSingleByChannel(Hit, ClosestLocation, ClosestLocation + FVector(0.0f, 0.0f, -LineTraceDistance), ECC_Visibility, IGNORE_OWNER_PARAMS)) { - const float SplineKey = CombatPath->FlattenSpline->FindInputKeyClosestToWorldLocation(Hit.ImpactPoint); - DistanceAlongSpline = CombatPath->FlattenSpline->GetDistanceAlongSplineAtSplineInputKey(SplineKey); + const float SplineKey = CombatPath->FlattenedSpline->FindInputKeyClosestToWorldLocation(Hit.ImpactPoint); + DistanceAlongSpline = CombatPath->FlattenedSpline->GetDistanceAlongSplineAtSplineInputKey(SplineKey); ClosestLocation.Z += CharacterOwner->GetCapsuleComponent()->GetScaledCapsuleHalfHeight(); UpdatedComponent->SetWorldLocation(ClosestLocation); @@ -117,8 +119,8 @@ bool UPwnCharacterMovementComponent::IsCustomMovementMode(const ECustomMovementM return MovementMode == MOVE_Custom && CustomMovementMode == Mode; } -void UPwnCharacterMovementComponent::RecomputeTangentAndAcceleration() { - Tangent2D = CombatPath->FlattenSpline->GetTangentAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World).GetSafeNormal2D(); +void UPwnCharacterMovementComponent::UpdateTangentAndAcceleration() { + Tangent2D = CombatPath->FlattenedSpline->GetTangentAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World).GetSafeNormal2D(); // Recalculate acceleration so the input is relative to the spline Acceleration = Tangent2D * Acceleration.Size2D() * FMath::Sign(Acceleration.X) * DotDirection; } @@ -135,32 +137,31 @@ void UPwnCharacterMovementComponent::UpdatePawnVelocity(const float TimeTick) { } VelocityDirection = FMath::Sign(VelocityDirection); // -1, 0 or 1 - float NewDistanceAlongSpline = DistanceAlongSpline + VelocityDirection * VelocitySize2D * TimeTick; - NewDistanceAlongSpline = FMath::Clamp(NewDistanceAlongSpline, 0.0f, CombatPath->FlattenSpline->GetSplineLength()); + DistanceAlongSpline = DistanceAlongSpline + VelocityDirection * VelocitySize2D * TimeTick; + DistanceAlongSpline = FMath::Clamp(DistanceAlongSpline, 0.0f, CombatPath->FlattenedSpline->GetSplineLength()); - FVector TargetLocation = CombatPath->FlattenSpline->GetLocationAtDistanceAlongSpline(NewDistanceAlongSpline, ESplineCoordinateSpace::World); + FVector TargetLocation = CombatPath->FlattenedSpline->GetLocationAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World); TargetLocation.Z = OldLocation.Z; const FVector Direction = (TargetLocation - OldLocation).GetSafeNormal2D(); Velocity = VelocitySize2D * Direction; Velocity.Z = OldVelocity.Z; - - DistanceAlongSpline = NewDistanceAlongSpline; } -void UPwnCharacterMovementComponent::UpdateDistanceAlongSplineAndLocation() { - // Maintain coherent distance along spline with location +void UPwnCharacterMovementComponent::UpdateDistanceAlongSpline() { FHitResult Hit; if (GetWorld()->LineTraceSingleByChannel(Hit, UpdatedComponent->GetComponentLocation(), - UpdatedComponent->GetComponentLocation() + FVector(0.0f, 0.0f, -10000.0f), - ECC_Visibility, IGNORE_OWNER_PARAMS)) { - - FVector ImpactPoint = Hit.ImpactPoint; - const float InputKey = CombatPath->FlattenSpline->FindInputKeyClosestToWorldLocation(ImpactPoint); - DistanceAlongSpline = CombatPath->FlattenSpline->GetDistanceAlongSplineAtSplineInputKey(InputKey); + UpdatedComponent->GetComponentLocation() + FVector(0.0f, 0.0f, -LineTraceDistance), + ECC_Visibility, IGNORE_OWNER_PARAMS)) { + const FVector ImpactPoint = Hit.ImpactPoint; + const float InputKey = CombatPath->FlattenedSpline->FindInputKeyClosestToWorldLocation(ImpactPoint); + DistanceAlongSpline = CombatPath->FlattenedSpline->GetDistanceAlongSplineAtSplineInputKey(InputKey); } +} - FVector TargetLocation = CombatPath->FlattenSpline->GetLocationAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World); +void UPwnCharacterMovementComponent::UpdateLocationOnFlattenedSpline() const { + // Maintain coherent distance along spline with location + FVector TargetLocation = CombatPath->FlattenedSpline->GetLocationAtDistanceAlongSpline(DistanceAlongSpline, ESplineCoordinateSpace::World); TargetLocation.Z = UpdatedComponent->GetComponentLocation().Z; UpdatedComponent->SetWorldLocation(TargetLocation); } @@ -202,7 +203,7 @@ void UPwnCharacterMovementComponent::PhysSplineWalking(const float DeltaTime, in const FVector OldLocation = UpdatedComponent->GetComponentLocation(); const FFindFloorResult OldFloor = CurrentFloor; - RecomputeTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */ + UpdateTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */ Acceleration.Z = 0.f; RestorePreAdditiveRootMotionVelocity(); @@ -362,7 +363,9 @@ void UPwnCharacterMovementComponent::PhysSplineWalking(const float DeltaTime, in MaintainHorizontalGroundVelocity(); } - UpdateDistanceAlongSplineAndLocation(); /* -- PAWN MODIFICATIONS -- */ + /* -- PAWN MODIFICATIONS -- */ + UpdateDistanceAlongSpline(); + UpdateLocationOnFlattenedSpline(); } UE_DISABLE_OPTIMIZATION @@ -372,7 +375,7 @@ void UPwnCharacterMovementComponent::PhysSplineFalling(const float DeltaTime, in return; } - RecomputeTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */ + UpdateTangentAndAcceleration(); /* -- PAWN MODIFICATIONS -- */ FVector FallAcceleration = GetFallingLateralAcceleration(DeltaTime); FallAcceleration.Z = 0.f; @@ -676,7 +679,9 @@ void UPwnCharacterMovementComponent::PhysSplineFalling(const float DeltaTime, in } } - UpdateDistanceAlongSplineAndLocation(); /* -- PAWN MODIFICATIONS -- */ + /* -- PAWN MODIFICATIONS -- */ + UpdateDistanceAlongSpline(); + UpdateLocationOnFlattenedSpline(); } UE_ENABLE_OPTIMIZATION diff --git a/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp b/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp index 2c03d20..f26c9c1 100644 --- a/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp +++ b/Pawn_Unreal/Source/Pawn/Private/GameplayModes/Combat/PwnCombatPlatformerPath.cpp @@ -21,10 +21,10 @@ void APwnCombatPlatformerPath::BeginPlay() { check(Subsystem); Subsystem->RegisterCombatPath(this); - FlattenSpline = NewObject(this, TEXT("FlattenSpline")); - FlattenSpline->SetClosedLoop(Spline->IsClosedLoop(), false); - FlattenSpline->ReparamStepsPerSegment = Spline->ReparamStepsPerSegment; - FlattenSpline->ClearSplinePoints(false); + FlattenedSpline = NewObject(this, TEXT("FlattenedSpline")); + FlattenedSpline->SetClosedLoop(Spline->IsClosedLoop(), false); + FlattenedSpline->ReparamStepsPerSegment = Spline->ReparamStepsPerSegment; + FlattenedSpline->ClearSplinePoints(false); const FVector FirstPointLocation = Spline->GetLocationAtSplinePoint(0, ESplineCoordinateSpace::World); const float FirstPointZ = FirstPointLocation.Z; @@ -33,17 +33,17 @@ void APwnCombatPlatformerPath::BeginPlay() { for (int i = 0; i < PointsCount; ++i) { FVector NewLocation = Spline->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::World); NewLocation.Z = FirstPointZ; - FlattenSpline->AddSplinePoint(NewLocation, ESplineCoordinateSpace::World, false); + FlattenedSpline->AddSplinePoint(NewLocation, ESplineCoordinateSpace::World, false); FVector ArriveTangent = Spline->GetArriveTangentAtSplinePoint(i, ESplineCoordinateSpace::World); FVector LeaveTangent = Spline->GetLeaveTangentAtSplinePoint(i, ESplineCoordinateSpace::World); ArriveTangent.Z = 0; LeaveTangent.Z = 0; - FlattenSpline->SetTangentsAtSplinePoint(i, ArriveTangent, LeaveTangent, ESplineCoordinateSpace::World, false); + FlattenedSpline->SetTangentsAtSplinePoint(i, ArriveTangent, LeaveTangent, ESplineCoordinateSpace::World, false); } - FlattenSpline->UpdateSpline(); + FlattenedSpline->UpdateSpline(); Super::BeginPlay(); } diff --git a/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h index 2faff65..d39bced 100644 --- a/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h +++ b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h @@ -34,7 +34,7 @@ protected: virtual void OnMovementModeChanged(EMovementMode PreviousMovementMode, uint8 PreviousCustomMode) override; virtual void UpdateCharacterStateBeforeMovement(float DeltaSeconds) override; - + virtual void PhysCustom(const float DeltaTime, int32 Iterations) override; public: @@ -43,19 +43,48 @@ public: UFUNCTION(BlueprintCallable, Category="CharacterMovement") void ExitSplineFollowMode(); - + + /** + * @return True if the movement component is in the specified custom movement mode. + */ UFUNCTION(BlueprintCallable, Category="CharacterMovement") bool IsCustomMovementMode(const ECustomMovementMode Mode) const; private: - void RecomputeTangentAndAcceleration(); - + /** + * Updates the tangent in function of the current distance along the spline. Then updates the acceleration so it will simulate an input in the + * direction of the tangent. + */ + void UpdateTangentAndAcceleration(); + + /** + * Updates the distance along the spline in function of the current velocity. Then updates the velocity so the Updated Component will move + * to the next location on the spline. + * @param TimeTick Delta time in seconds for this update + */ void UpdatePawnVelocity(const float TimeTick); - void UpdateDistanceAlongSplineAndLocation(); + /** + * Updates the distance along the spline. + * Trace a line from the current location of the Updated Component to the ground. Retrieves the closest point on the flattened spline to the + * intersection point. The distance along the spline is then updated. + */ + void UpdateDistanceAlongSpline(); + /** + * Updates the location of the Updated Component to match the current distance along the spline. Must be called once the distance along the spline + * has been updated. + */ + void UpdateLocationOnFlattenedSpline() const; + + /** + * Custom movement update so the Updated Component follows the spline. Same behavior as walking on the ground. + */ void PhysSplineWalking(const float DeltaTime, int32 Iterations); + /** + * Custom movement update so the Updated Component falls along the spline. Same behavior as falling. + */ void PhysSplineFalling(const float DeltaTime, int32 Iterations); public: diff --git a/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h b/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h index 13e4f2c..bb4ad8a 100644 --- a/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h +++ b/Pawn_Unreal/Source/Pawn/Public/GameplayModes/Combat/PwnCombatPlatformerPath.h @@ -29,5 +29,5 @@ public: bool SwapCamera; UPROPERTY(Transient, BlueprintReadOnly) - TObjectPtr FlattenSpline; + TObjectPtr FlattenedSpline; };