diff --git a/Content/AdvancedLocomotionV4/Blueprints/CharacterLogic/ALS_Player_Controller.uasset b/Content/AdvancedLocomotionV4/Blueprints/CharacterLogic/ALS_Player_Controller.uasset index 191f523e..142b66cf 100644 Binary files a/Content/AdvancedLocomotionV4/Blueprints/CharacterLogic/ALS_Player_Controller.uasset and b/Content/AdvancedLocomotionV4/Blueprints/CharacterLogic/ALS_Player_Controller.uasset differ diff --git a/Content/AdvancedLocomotionV4/Blueprints/UI/ALS_HUD.uasset b/Content/AdvancedLocomotionV4/Blueprints/UI/ALS_HUD.uasset index ca70f7b5..4c414b50 100644 Binary files a/Content/AdvancedLocomotionV4/Blueprints/UI/ALS_HUD.uasset and b/Content/AdvancedLocomotionV4/Blueprints/UI/ALS_HUD.uasset differ diff --git a/Source/ALSV4_CPP/Private/Character/ALSBaseCharacter.cpp b/Source/ALSV4_CPP/Private/Character/ALSBaseCharacter.cpp index 737a22a9..5973235b 100644 --- a/Source/ALSV4_CPP/Private/Character/ALSBaseCharacter.cpp +++ b/Source/ALSV4_CPP/Private/Character/ALSBaseCharacter.cpp @@ -12,6 +12,8 @@ #include "Character/Animation/ALSCharacterAnimInstance.h" #include "Character/Animation/ALSPlayerCameraBehavior.h" #include "Library/ALSMathLibrary.h" +#include "Components/ALSDebugComponent.h" + #include "Components/CapsuleComponent.h" #include "Components/TimelineComponent.h" #include "Curves/CurveFloat.h" @@ -151,6 +153,8 @@ void AALSBaseCharacter::BeginPlay() { MainAnimInstance->SetRootMotionMode(ERootMotionMode::IgnoreRootMotion); } + + DebugComponent = FindComponentByClass(); } void AALSBaseCharacter::PreInitializeComponents() @@ -752,12 +756,28 @@ void AALSBaseCharacter::SetActorLocationDuringRagdoll(float DeltaTime) const FVector TraceVect(TargetRagdollLocation.X, TargetRagdollLocation.Y, TargetRagdollLocation.Z - GetCapsuleComponent()->GetScaledCapsuleHalfHeight()); + UWorld* World = GetWorld(); + check(World); + FCollisionQueryParams Params; Params.AddIgnoredActor(this); FHitResult HitResult; - GetWorld()->LineTraceSingleByChannel(HitResult, TargetRagdollLocation, TraceVect, - ECC_Visibility, Params); + const bool bHit = World->LineTraceSingleByChannel(HitResult, TargetRagdollLocation, TraceVect, + ECC_Visibility, Params); + + if (DebugComponent && DebugComponent->GetShowTraces()) + { + UALSDebugComponent::DrawDebugLineTraceSingle(World, + TargetRagdollLocation, + TraceVect, + EDrawDebugTrace::Type::ForOneFrame, + bHit, + HitResult, + FLinearColor::Red, + FLinearColor::Green, + 1.0f); + } bRagdollOnGround = HitResult.IsValidBlockingHit(); FVector NewRagdollLoc = TargetRagdollLocation; diff --git a/Source/ALSV4_CPP/Private/Character/ALSPlayerCameraManager.cpp b/Source/ALSV4_CPP/Private/Character/ALSPlayerCameraManager.cpp index f8bb5fb2..f67a14ce 100644 --- a/Source/ALSV4_CPP/Private/Character/ALSPlayerCameraManager.cpp +++ b/Source/ALSV4_CPP/Private/Character/ALSPlayerCameraManager.cpp @@ -12,6 +12,8 @@ #include "Character/ALSBaseCharacter.h" #include "Character/ALSPlayerController.h" #include "Character/Animation/ALSPlayerCameraBehavior.h" +#include "Components/ALSDebugComponent.h" + #include "Kismet/KismetMathLibrary.h" @@ -61,6 +63,8 @@ void AALSPlayerCameraManager::OnPossess(AALSBaseCharacter* NewCharacter) const FVector& TPSLoc = ControlledCharacter->GetThirdPersonPivotTarget().GetLocation(); SetActorLocation(TPSLoc); SmoothedPivotTarget.SetLocation(TPSLoc); + + DebugComponent = ControlledCharacter->FindComponentByClass(); } float AALSPlayerCameraManager::GetCameraBehaviorParam(FName CurveName) const @@ -183,8 +187,23 @@ bool AALSPlayerCameraManager::CustomCameraBehavior(float DeltaTime, FVector& Loc Params.AddIgnoredActor(ControlledCharacter); FHitResult HitResult; - World->SweepSingleByChannel(HitResult, TraceOrigin, TargetCameraLocation, FQuat::Identity, - TraceChannel, FCollisionShape::MakeSphere(TraceRadius), Params); + const FCollisionShape SphereCollisionShape = FCollisionShape::MakeSphere(TraceRadius); + const bool bHit = World->SweepSingleByChannel(HitResult, TraceOrigin, TargetCameraLocation, FQuat::Identity, + TraceChannel, SphereCollisionShape, Params); + + if (DebugComponent && DebugComponent->GetShowTraces()) + { + UALSDebugComponent::DrawDebugSphereTraceSingle(World, + TraceOrigin, + TargetCameraLocation, + SphereCollisionShape, + EDrawDebugTrace::Type::ForOneFrame, + bHit, + HitResult, + FLinearColor::Red, + FLinearColor::Green, + 5.0f); + } if (HitResult.IsValidBlockingHit()) { diff --git a/Source/ALSV4_CPP/Private/Character/ALSPlayerController.cpp b/Source/ALSV4_CPP/Private/Character/ALSPlayerController.cpp index 1168ce6f..75d4ba75 100644 --- a/Source/ALSV4_CPP/Private/Character/ALSPlayerController.cpp +++ b/Source/ALSV4_CPP/Private/Character/ALSPlayerController.cpp @@ -61,14 +61,16 @@ void AALSPlayerController::SetupDebugInputs() UALSDebugComponent* DebugComp = Cast(Comp); if (InputComponent && DebugComp) { - InputComponent->BindKey(FKey("Tab"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleHud); - InputComponent->BindKey(FKey("V"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleDebugView); - InputComponent->BindKey(FKey("T"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleTraces); - InputComponent->BindKey(FKey("Y"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleDebugShapes); - InputComponent->BindKey(FKey("U"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleLayerColors); - InputComponent->BindKey(FKey("I"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleCharacterInfo); - InputComponent->BindKey(FKey("Z"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleSlomo); - InputComponent->BindKey(FKey("M"), EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleDebugMesh); + InputComponent->BindKey(EKeys::Tab, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleHud); + InputComponent->BindKey(EKeys::V, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleDebugView); + InputComponent->BindKey(EKeys::T, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleTraces); + InputComponent->BindKey(EKeys::Y, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleDebugShapes); + InputComponent->BindKey(EKeys::U, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleLayerColors); + InputComponent->BindKey(EKeys::I, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleCharacterInfo); + InputComponent->BindKey(EKeys::Z, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleSlomo); + InputComponent->BindKey(EKeys::Comma, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::PreviousFocusedDebugCharacter); + InputComponent->BindKey(EKeys::Period, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::NextFocusedDebugCharacter); + InputComponent->BindKey(EKeys::M, EInputEvent::IE_Pressed, DebugComp, &UALSDebugComponent::ToggleDebugMesh); } } } diff --git a/Source/ALSV4_CPP/Private/Character/Animation/ALSCharacterAnimInstance.cpp b/Source/ALSV4_CPP/Private/Character/Animation/ALSCharacterAnimInstance.cpp index 2454480c..9a39dbf2 100644 --- a/Source/ALSV4_CPP/Private/Character/Animation/ALSCharacterAnimInstance.cpp +++ b/Source/ALSV4_CPP/Private/Character/Animation/ALSCharacterAnimInstance.cpp @@ -9,6 +9,8 @@ #include "Character/Animation/ALSCharacterAnimInstance.h" #include "Character/ALSBaseCharacter.h" #include "Library/ALSMathLibrary.h" +#include "Components/ALSDebugComponent.h" + #include "Curves/CurveVector.h" #include "Components/CapsuleComponent.h" #include "GameFramework/CharacterMovementComponent.h" @@ -53,6 +55,17 @@ void UALSCharacterAnimInstance::NativeInitializeAnimation() Character = Cast(TryGetPawnOwner()); } +void UALSCharacterAnimInstance::NativeBeginPlay() +{ + // it seems to be that the player pawn components are not really initialized + // when the call to NativeInitializeAnimation() happens. + // This is the reason why it is tried here to get the ALS debug component. + if (APawn* Owner = TryGetPawnOwner()) + { + DebugComponent = Owner->FindComponentByClass(); + } +} + void UALSCharacterAnimInstance::NativeUpdateAnimation(float DeltaSeconds) { Super::NativeUpdateAnimation(DeltaSeconds); @@ -458,11 +471,28 @@ void UALSCharacterAnimInstance::SetFootOffsets(float DeltaSeconds, FName EnableF FCollisionQueryParams Params; Params.AddIgnoredActor(Character); + const FVector TraceStart = IKFootFloorLoc + FVector(0.0, 0.0, Config.IK_TraceDistanceAboveFoot); + const FVector TraceEnd = IKFootFloorLoc - FVector(0.0, 0.0, Config.IK_TraceDistanceBelowFoot); + FHitResult HitResult; - World->LineTraceSingleByChannel(HitResult, - IKFootFloorLoc + FVector(0.0, 0.0, Config.IK_TraceDistanceAboveFoot), - IKFootFloorLoc - FVector(0.0, 0.0, Config.IK_TraceDistanceBelowFoot), - ECC_Visibility, Params); + const bool bHit = World->LineTraceSingleByChannel(HitResult, + TraceStart, + TraceEnd, + ECC_Visibility, Params); + + if (DebugComponent && DebugComponent->GetShowTraces()) + { + UALSDebugComponent::DrawDebugLineTraceSingle( + World, + TraceStart, + TraceEnd, + EDrawDebugTrace::Type::ForOneFrame, + bHit, + HitResult, + FLinearColor::Red, + FLinearColor::Green, + 5.0f); + } FRotator TargetRotOffset = FRotator::ZeroRotator; if (Character->GetCharacterMovement()->IsWalkable(HitResult)) @@ -769,11 +799,25 @@ float UALSCharacterAnimInstance::CalculateLandPrediction() const Params.AddIgnoredActor(Character); FHitResult HitResult; - - World->SweepSingleByChannel(HitResult, CapsuleWorldLoc, CapsuleWorldLoc + TraceLength, FQuat::Identity, - ECC_Visibility, - FCollisionShape::MakeCapsule(CapsuleComp->GetUnscaledCapsuleRadius(), - CapsuleComp->GetUnscaledCapsuleHalfHeight()), Params); + const FCollisionShape CapsuleCollisionShape = FCollisionShape::MakeCapsule(CapsuleComp->GetUnscaledCapsuleRadius(), + CapsuleComp->GetUnscaledCapsuleHalfHeight()); + const float HalfHeight = 0.0f; + const bool bHit = World->SweepSingleByChannel(HitResult, CapsuleWorldLoc, CapsuleWorldLoc + TraceLength, FQuat::Identity, + ECC_Visibility, CapsuleCollisionShape, Params); + + if (DebugComponent && DebugComponent->GetShowTraces()) + { + UALSDebugComponent::DrawDebugCapsuleTraceSingle(World, + CapsuleWorldLoc, + CapsuleWorldLoc + TraceLength, + CapsuleCollisionShape, + EDrawDebugTrace::Type::ForOneFrame, + bHit, + HitResult, + FLinearColor::Red, + FLinearColor::Green, + 5.0f); + } if (Character->GetCharacterMovement()->IsWalkable(HitResult)) { diff --git a/Source/ALSV4_CPP/Private/Components/ALSDebugComponent.cpp b/Source/ALSV4_CPP/Private/Components/ALSDebugComponent.cpp index ba650ece..879fcff9 100644 --- a/Source/ALSV4_CPP/Private/Components/ALSDebugComponent.cpp +++ b/Source/ALSV4_CPP/Private/Components/ALSDebugComponent.cpp @@ -3,21 +3,21 @@ // License: MIT License (http://www.opensource.org/licenses/mit-license.php) // Source Code: https://github.com/dyanikoglu/ALSV4_CPP // Original Author: Doğa Can Yanıkoğlu -// Contributors: +// Contributors: Achim Turan #include "Components/ALSDebugComponent.h" #include "Character/ALSBaseCharacter.h" -#include "Character/ALSCharacter.h" #include "Character/ALSPlayerCameraManager.h" #include "Character/Animation/ALSPlayerCameraBehavior.h" #include "Kismet/GameplayStatics.h" +#include "DrawDebugHelpers.h" -bool UALSDebugComponent::bDebugView; -bool UALSDebugComponent::bShowTraces; -bool UALSDebugComponent::bShowDebugShapes; -bool UALSDebugComponent::bShowLayerColors; +bool UALSDebugComponent::bDebugView = false; +bool UALSDebugComponent::bShowTraces = false; +bool UALSDebugComponent::bShowDebugShapes = false; +bool UALSDebugComponent::bShowLayerColors = false; UALSDebugComponent::UALSDebugComponent() { @@ -82,17 +82,75 @@ void UALSDebugComponent::OnComponentDestroyed(bool bDestroyingHierarchy) bShowLayerColors = false; } +void UALSDebugComponent::PreviousFocusedDebugCharacter() +{ + if (FocusedDebugCharacterIndex == INDEX_NONE) + { // Return here as no AALSBaseCharacter where found during call of BeginPlay. + // Moreover, for savety set also no focused debug character. + DebugFocusCharacter = nullptr; + return; + } + + FocusedDebugCharacterIndex++; + if (FocusedDebugCharacterIndex >= AvailableDebugCharacters.Num()) { + FocusedDebugCharacterIndex = 0; + } + + DebugFocusCharacter = AvailableDebugCharacters[FocusedDebugCharacterIndex]; +} + +void UALSDebugComponent::NextFocusedDebugCharacter() +{ + if (FocusedDebugCharacterIndex == INDEX_NONE) + { // Return here as no AALSBaseCharacter where found during call of BeginPlay. + // Moreover, for savety set also no focused debug character. + DebugFocusCharacter = nullptr; + return; + } + + FocusedDebugCharacterIndex--; + if (FocusedDebugCharacterIndex < 0) { + FocusedDebugCharacterIndex = AvailableDebugCharacters.Num() - 1; + } + + DebugFocusCharacter = AvailableDebugCharacters[FocusedDebugCharacterIndex]; +} + void UALSDebugComponent::BeginPlay() { Super::BeginPlay(); - OwnerCharacter = Cast(GetOwner()); - + OwnerCharacter = Cast(GetOwner()); + DebugFocusCharacter = OwnerCharacter; if (OwnerCharacter) { SetDynamicMaterials(); SetResetColors(); } + + // Get all ALSBaseCharacter's, which are currently present to show them later in the ALS HUD for debugging purposes. + TArray AlsBaseCharacters; + UGameplayStatics::GetAllActorsOfClass(GetWorld(), AALSBaseCharacter::StaticClass(), AlsBaseCharacters); + + AvailableDebugCharacters.Empty(); + if (AlsBaseCharacters.Num() > 0) + { + AvailableDebugCharacters.Reserve(AlsBaseCharacters.Num()); + for (AActor* Character : AlsBaseCharacters) + { + if (AALSBaseCharacter* AlsBaseCharacter = Cast(Character)) + { + AvailableDebugCharacters.Add(AlsBaseCharacter); + } + } + + FocusedDebugCharacterIndex = AvailableDebugCharacters.Find(DebugFocusCharacter); + if (FocusedDebugCharacterIndex == INDEX_NONE && AvailableDebugCharacters.Num() > 0) + { // seems to be that this component was not attached to and AALSBaseCharacter, + // therefore the index will be set to the first element in the array. + FocusedDebugCharacterIndex = 0; + } + } } void UALSDebugComponent::ToggleGlobalTimeDilationLocal(float TimeDilation) @@ -139,3 +197,124 @@ void UALSDebugComponent::ToggleDebugMesh() } bDebugMeshVisible = !bDebugMeshVisible; } + + +/** Util for drawing result of single line trace */ +void UALSDebugComponent::DrawDebugLineTraceSingle(const UWorld* World, + const FVector& Start, + const FVector& End, + EDrawDebugTrace::Type + DrawDebugType, + bool bHit, + const FHitResult& OutHit, + FLinearColor TraceColor, + FLinearColor TraceHitColor, + float DrawTime) +{ + if (DrawDebugType != EDrawDebugTrace::None) + { + bool bPersistent = DrawDebugType == EDrawDebugTrace::Persistent; + float LifeTime = (DrawDebugType == EDrawDebugTrace::ForDuration) ? DrawTime : 0.f; + + if (bHit && OutHit.bBlockingHit) + { + // Red up to the blocking hit, green thereafter + ::DrawDebugLine(World, Start, OutHit.ImpactPoint, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugLine(World, OutHit.ImpactPoint, End, TraceHitColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugPoint(World, OutHit.ImpactPoint, 16.0f, TraceColor.ToFColor(true), bPersistent, LifeTime); + } + else + { + // no hit means all red + ::DrawDebugLine(World, Start, End, TraceColor.ToFColor(true), bPersistent, LifeTime); + } + } +} + +void UALSDebugComponent::DrawDebugCapsuleTraceSingle(const UWorld* World, + const FVector& Start, + const FVector& End, + const FCollisionShape& CollisionShape, + EDrawDebugTrace::Type DrawDebugType, + bool bHit, + const FHitResult& OutHit, + FLinearColor TraceColor, + FLinearColor TraceHitColor, + float DrawTime) +{ + if (DrawDebugType != EDrawDebugTrace::None) + { + bool bPersistent = DrawDebugType == EDrawDebugTrace::Persistent; + float LifeTime = (DrawDebugType == EDrawDebugTrace::ForDuration) ? DrawTime : 0.f; + + if (bHit && OutHit.bBlockingHit) + { + // Red up to the blocking hit, green thereafter + ::DrawDebugCapsule(World, Start, CollisionShape.GetCapsuleHalfHeight(), CollisionShape.GetCapsuleRadius(), FQuat::Identity, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugCapsule(World, OutHit.Location, CollisionShape.GetCapsuleHalfHeight(), CollisionShape.GetCapsuleRadius(), FQuat::Identity, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugLine(World, Start, OutHit.Location, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugPoint(World, OutHit.ImpactPoint, 16.0f, TraceColor.ToFColor(true), bPersistent, LifeTime); + + ::DrawDebugCapsule(World, End, CollisionShape.GetCapsuleHalfHeight(), CollisionShape.GetCapsuleRadius(), FQuat::Identity, TraceHitColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugLine(World, OutHit.Location, End, TraceHitColor.ToFColor(true), bPersistent, LifeTime); + } + else + { + // no hit means all red + ::DrawDebugCapsule(World, Start, CollisionShape.GetCapsuleHalfHeight(), CollisionShape.GetCapsuleRadius(), FQuat::Identity, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugCapsule(World, End, CollisionShape.GetCapsuleHalfHeight(), CollisionShape.GetCapsuleRadius(), FQuat::Identity, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugLine(World, Start, End, TraceColor.ToFColor(true), bPersistent, LifeTime); + } + } +} + +static void DrawDebugSweptSphere(const UWorld* InWorld, + FVector const& Start, + FVector const& End, + float Radius, + FColor const& Color, + bool bPersistentLines = false, + float LifeTime = -1.f, + uint8 DepthPriority = 0) +{ + FVector const TraceVec = End - Start; + float const Dist = TraceVec.Size(); + + FVector const Center = Start + TraceVec * 0.5f; + float const HalfHeight = (Dist * 0.5f) + Radius; + + FQuat const CapsuleRot = FRotationMatrix::MakeFromZ(TraceVec).ToQuat(); + ::DrawDebugCapsule(InWorld, Center, HalfHeight, Radius, CapsuleRot, Color, bPersistentLines, LifeTime, DepthPriority); +} + +void UALSDebugComponent::DrawDebugSphereTraceSingle(const UWorld* World, + const FVector& Start, + const FVector& End, + const FCollisionShape& CollisionShape, + EDrawDebugTrace::Type DrawDebugType, + bool bHit, + const FHitResult& OutHit, + FLinearColor TraceColor, + FLinearColor TraceHitColor, + float DrawTime) +{ + if (DrawDebugType != EDrawDebugTrace::None) + { + bool bPersistent = DrawDebugType == EDrawDebugTrace::Persistent; + float LifeTime = (DrawDebugType == EDrawDebugTrace::ForDuration) ? DrawTime : 0.f; + + if (bHit && OutHit.bBlockingHit) + { + // Red up to the blocking hit, green thereafter + ::DrawDebugSweptSphere(World, Start, OutHit.Location, CollisionShape.GetSphereRadius(), TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugSweptSphere(World, OutHit.Location, End, CollisionShape.GetSphereRadius(), TraceHitColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugPoint(World, OutHit.ImpactPoint, 16.0f, TraceColor.ToFColor(true), bPersistent, LifeTime); + } + else + { + // no hit means all red + ::DrawDebugSweptSphere(World, Start, End, CollisionShape.GetSphereRadius(), TraceColor.ToFColor(true), bPersistent, LifeTime); + } + } +} + diff --git a/Source/ALSV4_CPP/Private/Components/ALSMantleComponent.cpp b/Source/ALSV4_CPP/Private/Components/ALSMantleComponent.cpp index de49f08b..4733f7f0 100644 --- a/Source/ALSV4_CPP/Private/Components/ALSMantleComponent.cpp +++ b/Source/ALSV4_CPP/Private/Components/ALSMantleComponent.cpp @@ -10,6 +10,7 @@ #include "Character/ALSCharacter.h" #include "Character/Animation/ALSCharacterAnimInstance.h" +#include "Components/ALSDebugComponent.h" #include "Curves/CurveVector.h" #include "GameFramework/CharacterMovementComponent.h" #include "Kismet/KismetMathLibrary.h" @@ -55,6 +56,8 @@ void UALSMantleComponent::BeginPlay() OwnerCharacter->JumpPressedDelegate.AddUniqueDynamic(this, &UALSMantleComponent::OnOwnerJumpInput); OwnerCharacter->RagdollStateChangedDelegate.AddUniqueDynamic( this, &UALSMantleComponent::OnOwnerRagdollStateChanged); + + DebugComponent = OwnerCharacter->FindComponentByClass(); } } } @@ -65,12 +68,12 @@ void UALSMantleComponent::TickComponent(float DeltaTime, ELevelTick TickType, { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); - if (OwnerCharacter->GetMovementState() == EALSMovementState::InAir) + if (OwnerCharacter && OwnerCharacter->GetMovementState() == EALSMovementState::InAir) { // Perform a mantle check if falling while movement input is pressed. if (OwnerCharacter->HasMovementInput()) { - MantleCheck(FallingTraceSettings); + MantleCheck(FallingTraceSettings, EDrawDebugTrace::Type::ForOneFrame); } } } @@ -173,8 +176,25 @@ bool UALSMantleComponent::MantleCheck(const FALSMantleTraceSettings& TraceSettin Params.AddIgnoredActor(OwnerCharacter); FHitResult HitResult; - World->SweepSingleByProfile(HitResult, TraceStart, TraceEnd, FQuat::Identity, MantleObjectDetectionProfile, - FCollisionShape::MakeCapsule(TraceSettings.ForwardTraceRadius, HalfHeight), Params); + { + const FCollisionShape CapsuleCollisionShape = FCollisionShape::MakeCapsule(TraceSettings.ForwardTraceRadius, HalfHeight); + const bool bHit = World->SweepSingleByProfile(HitResult, TraceStart, TraceEnd, FQuat::Identity, MantleObjectDetectionProfile, + CapsuleCollisionShape, Params); + + if (DebugComponent && DebugComponent->GetShowTraces()) + { + UALSDebugComponent::DrawDebugCapsuleTraceSingle(World, + TraceStart, + TraceEnd, + CapsuleCollisionShape, + DebugType, + bHit, + HitResult, + FLinearColor::Black, + FLinearColor::Black, + 1.0f); + } + } if (!HitResult.IsValidBlockingHit() || OwnerCharacter->GetCharacterMovement()->IsWalkable(HitResult)) { @@ -202,9 +222,26 @@ bool UALSMantleComponent::MantleCheck(const FALSMantleTraceSettings& TraceSettin FVector DownwardTraceStart = DownwardTraceEnd; DownwardTraceStart.Z += TraceSettings.MaxLedgeHeight + TraceSettings.DownwardTraceRadius + 1.0f; - World->SweepSingleByChannel(HitResult, DownwardTraceStart, DownwardTraceEnd, FQuat::Identity, - WalkableSurfaceDetectionChannel, FCollisionShape::MakeSphere(TraceSettings.DownwardTraceRadius), - Params); + { + const FCollisionShape SphereCollisionShape = FCollisionShape::MakeSphere(TraceSettings.DownwardTraceRadius); + const bool bHit = World->SweepSingleByChannel(HitResult, DownwardTraceStart, DownwardTraceEnd, FQuat::Identity, + WalkableSurfaceDetectionChannel, SphereCollisionShape, + Params); + + if (DebugComponent && DebugComponent->GetShowTraces()) + { + UALSDebugComponent::DrawDebugSphereTraceSingle(World, + TraceStart, + TraceEnd, + SphereCollisionShape, + DebugType, + bHit, + HitResult, + FLinearColor::Black, + FLinearColor::Black, + 1.0f); + } + } if (!OwnerCharacter->GetCharacterMovement()->IsWalkable(HitResult)) @@ -222,7 +259,7 @@ bool UALSMantleComponent::MantleCheck(const FALSMantleTraceSettings& TraceSettin DownTraceLocation, 2.0f, OwnerCharacter->GetCapsuleComponent()); const bool bCapsuleHasRoom = UALSMathLibrary::CapsuleHasRoomCheck(OwnerCharacter->GetCapsuleComponent(), CapsuleLocationFBase, 0.0f, - 0.0f); + 0.0f, DebugType, DebugComponent && DebugComponent->GetShowTraces()); if (!bCapsuleHasRoom) { @@ -369,12 +406,12 @@ void UALSMantleComponent::OnOwnerJumpInput() { if (OwnerCharacter->HasMovementInput()) { - MantleCheck(GroundedTraceSettings); + MantleCheck(GroundedTraceSettings, EDrawDebugTrace::Type::ForDuration); } } else if (OwnerCharacter->GetMovementState() == EALSMovementState::InAir) { - MantleCheck(FallingTraceSettings); + MantleCheck(FallingTraceSettings, EDrawDebugTrace::Type::ForDuration); } } } diff --git a/Source/ALSV4_CPP/Private/Library/ALSMathLibrary.cpp b/Source/ALSV4_CPP/Private/Library/ALSMathLibrary.cpp index 295b16fa..75210468 100644 --- a/Source/ALSV4_CPP/Private/Library/ALSMathLibrary.cpp +++ b/Source/ALSV4_CPP/Private/Library/ALSMathLibrary.cpp @@ -3,11 +3,15 @@ // License: MIT License (http://www.opensource.org/licenses/mit-license.php) // Source Code: https://github.com/dyanikoglu/ALSV4_CPP // Original Author: Doğa Can Yanıkoğlu -// Contributors: +// Contributors: Achim Turan #include "Library/ALSMathLibrary.h" + +#include "Library/ALSCharacterStructLibrary.h" +#include "Components/ALSDebugComponent.h" + #include "Components/CapsuleComponent.h" FTransform UALSMathLibrary::MantleComponentLocalToWorld(const FALSComponentAndTransform& CompAndTransform) @@ -44,7 +48,7 @@ FVector UALSMathLibrary::GetCapsuleLocationFromBase(FVector BaseLocation, const } bool UALSMathLibrary::CapsuleHasRoomCheck(UCapsuleComponent* Capsule, FVector TargetLocation, float HeightOffset, - float RadiusOffset) + float RadiusOffset, EDrawDebugTrace::Type DebugType, bool DrawDebugTrace) { // Perform a trace to see if the capsule has room to be at the target location. const float ZTarget = Capsule->GetScaledCapsuleHalfHeight_WithoutHemisphere() - RadiusOffset + HeightOffset; @@ -61,8 +65,23 @@ bool UALSMathLibrary::CapsuleHasRoomCheck(UCapsuleComponent* Capsule, FVector Ta Params.AddIgnoredActor(Capsule->GetOwner()); FHitResult HitResult; - World->SweepSingleByChannel(HitResult, TraceStart, TraceEnd, FQuat::Identity, - ECC_Visibility, FCollisionShape::MakeSphere(Radius), Params); + const FCollisionShape SphereCollisionShape = FCollisionShape::MakeSphere(Radius); + const bool bHit = World->SweepSingleByChannel(HitResult, TraceStart, TraceEnd, FQuat::Identity, + ECC_Visibility, FCollisionShape::MakeSphere(Radius), Params); + + if (DrawDebugTrace) + { + UALSDebugComponent::DrawDebugSphereTraceSingle(World, + TraceStart, + TraceEnd, + SphereCollisionShape, + DebugType, + bHit, + HitResult, + FLinearColor(0.130706f, 0.896269f, 0.144582f, 1.0f), // light green + FLinearColor(0.932733f, 0.29136f, 1.0f, 1.0f), // light purple + 1.0f); + } return !(HitResult.bBlockingHit || HitResult.bStartPenetrating); } diff --git a/Source/ALSV4_CPP/Public/Character/ALSBaseCharacter.h b/Source/ALSV4_CPP/Public/Character/ALSBaseCharacter.h index da7e6435..e296762c 100644 --- a/Source/ALSV4_CPP/Public/Character/ALSBaseCharacter.h +++ b/Source/ALSV4_CPP/Public/Character/ALSBaseCharacter.h @@ -17,6 +17,8 @@ #include "ALSBaseCharacter.generated.h" +// forward declarations +class UALSDebugComponent; class UTimelineComponent; class UAnimInstance; class UAnimMontage; @@ -644,4 +646,7 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter /** We won't use curve based movement and a few other features on networked games */ bool bEnableNetworkOptimizations = false; + +private: + UALSDebugComponent* DebugComponent = nullptr; }; diff --git a/Source/ALSV4_CPP/Public/Character/ALSPlayerCameraManager.h b/Source/ALSV4_CPP/Public/Character/ALSPlayerCameraManager.h index b05a956d..4a0d96f2 100644 --- a/Source/ALSV4_CPP/Public/Character/ALSPlayerCameraManager.h +++ b/Source/ALSV4_CPP/Public/Character/ALSPlayerCameraManager.h @@ -12,6 +12,8 @@ #include "Camera/PlayerCameraManager.h" #include "ALSPlayerCameraManager.generated.h" +// forward declarations +class UALSDebugComponent; class AALSBaseCharacter; /** @@ -73,4 +75,7 @@ class ALSV4_CPP_API AALSPlayerCameraManager : public APlayerCameraManager UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ALS|Camera") FVector DebugViewOffset; + +private: + UALSDebugComponent* DebugComponent = nullptr; }; diff --git a/Source/ALSV4_CPP/Public/Character/Animation/ALSCharacterAnimInstance.h b/Source/ALSV4_CPP/Public/Character/Animation/ALSCharacterAnimInstance.h index 316e1d3d..de09bdd4 100644 --- a/Source/ALSV4_CPP/Public/Character/Animation/ALSCharacterAnimInstance.h +++ b/Source/ALSV4_CPP/Public/Character/Animation/ALSCharacterAnimInstance.h @@ -15,6 +15,8 @@ #include "ALSCharacterAnimInstance.generated.h" +// forward declarations +class UALSDebugComponent; class AALSBaseCharacter; class UCurveFloat; class UAnimSequence; @@ -31,6 +33,8 @@ class ALSV4_CPP_API UALSCharacterAnimInstance : public UAnimInstance public: virtual void NativeInitializeAnimation() override; + virtual void NativeBeginPlay() override; + virtual void NativeUpdateAnimation(float DeltaSeconds) override; UFUNCTION(BlueprintCallable, Category = "ALS|Animation") @@ -315,4 +319,6 @@ class ALSV4_CPP_API UALSCharacterAnimInstance : public UAnimInstance FTimerHandle OnJumpedTimer; bool bCanPlayDynamicTransition = true; + + UALSDebugComponent* DebugComponent = nullptr; }; diff --git a/Source/ALSV4_CPP/Public/Components/ALSDebugComponent.h b/Source/ALSV4_CPP/Public/Components/ALSDebugComponent.h index 783fb3ce..900be31a 100644 --- a/Source/ALSV4_CPP/Public/Components/ALSDebugComponent.h +++ b/Source/ALSV4_CPP/Public/Components/ALSDebugComponent.h @@ -3,16 +3,17 @@ // License: MIT License (http://www.opensource.org/licenses/mit-license.php) // Source Code: https://github.com/dyanikoglu/ALSV4_CPP // Original Author: Doğa Can Yanıkoğlu -// Contributors: +// Contributors: Achim Turan #pragma once #include "CoreMinimal.h" +#include "Kismet/KismetSystemLibrary.h" #include "Components/ActorComponent.h" #include "ALSDebugComponent.generated.h" -class AALSCharacter; +class AALSBaseCharacter; UCLASS(Blueprintable, BlueprintType) class ALSV4_CPP_API UALSDebugComponent : public UActorComponent @@ -82,12 +83,54 @@ class ALSV4_CPP_API UALSDebugComponent : public UActorComponent UFUNCTION(BlueprintCallable, Category = "ALS|Debug") bool GetShowLayerColors() { return bShowLayerColors; } + UFUNCTION(BlueprintCallable, Category = "ALS|Debug") + void PreviousFocusedDebugCharacter(); + + UFUNCTION(BlueprintCallable, Category = "ALS|Debug") + void NextFocusedDebugCharacter(); + + // utility functions to draw trace debug shapes, + // which are derived from Engine/Private/KismetTraceUtils.h. + // Sadly the functions are private, which was the reason + // why there reimplemented here. + static void DrawDebugLineTraceSingle(const UWorld* World, + const FVector& Start, + const FVector& End, + EDrawDebugTrace::Type DrawDebugType, + bool bHit, + const FHitResult& OutHit, + FLinearColor TraceColor, + FLinearColor TraceHitColor, + float DrawTime); + + static void DrawDebugCapsuleTraceSingle(const UWorld* World, + const FVector& Start, + const FVector& End, + const FCollisionShape& CollisionShape, + EDrawDebugTrace::Type DrawDebugType, + bool bHit, + const FHitResult& OutHit, + FLinearColor TraceColor, + FLinearColor TraceHitColor, + float DrawTime); + + static void DrawDebugSphereTraceSingle(const UWorld* World, + const FVector& Start, + const FVector& End, + const FCollisionShape& CollisionShape, + EDrawDebugTrace::Type DrawDebugType, + bool bHit, + const FHitResult& OutHit, + FLinearColor TraceColor, + FLinearColor TraceHitColor, + float DrawTime); + protected: virtual void BeginPlay() override; public: UPROPERTY(BlueprintReadOnly, Category = "ALS|Debug") - AALSCharacter* OwnerCharacter; + AALSBaseCharacter* OwnerCharacter; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "ALS|Debug") bool bSlomo = false; @@ -100,7 +143,13 @@ class ALSV4_CPP_API UALSDebugComponent : public UActorComponent UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "ALS|Debug") USkeletalMesh* DebugSkeletalMesh = nullptr; + + UPROPERTY(BlueprintReadOnly, Category = "ALS|Debug") + TArray AvailableDebugCharacters; + UPROPERTY(BlueprintReadOnly, Category = "ALS|Debug") + AALSBaseCharacter* DebugFocusCharacter = nullptr; +private: static bool bDebugView; static bool bShowTraces; @@ -109,11 +158,14 @@ class ALSV4_CPP_API UALSDebugComponent : public UActorComponent static bool bShowLayerColors; -private: bool bNeedsColorReset = false; bool bDebugMeshVisible = false; - UPROPERTY() USkeletalMesh* DefaultSkeletalMesh = nullptr; + + /// Stores the index, which is used to select the next focused debug ALSBaseCharacter. + /// If no characters where found during BeginPlay the value should be set to INDEX_NONE. + int32 FocusedDebugCharacterIndex = INDEX_NONE; }; + diff --git a/Source/ALSV4_CPP/Public/Components/ALSMantleComponent.h b/Source/ALSV4_CPP/Public/Components/ALSMantleComponent.h index c5956f58..9aeaa1a9 100644 --- a/Source/ALSV4_CPP/Public/Components/ALSMantleComponent.h +++ b/Source/ALSV4_CPP/Public/Components/ALSMantleComponent.h @@ -14,6 +14,9 @@ #include "ALSMantleComponent.generated.h" +// forward declarations +class UALSDebugComponent; + UCLASS(Blueprintable, BlueprintType) class ALSV4_CPP_API UALSMantleComponent : public UActorComponent @@ -23,12 +26,9 @@ class ALSV4_CPP_API UALSMantleComponent : public UActorComponent public: UALSMantleComponent(); - virtual void TickComponent(float DeltaTime, ELevelTick TickType, - FActorComponentTickFunction* ThisTickFunction) override; - UFUNCTION(BlueprintCallable, Category = "ALS|Mantle System") bool MantleCheck(const FALSMantleTraceSettings& TraceSettings, - EDrawDebugTrace::Type DebugType = EDrawDebugTrace::Type::None); + EDrawDebugTrace::Type DebugType); UFUNCTION(BlueprintCallable, Category = "ALS|Mantle System") void MantleStart(float MantleHeight, const FALSComponentAndTransform& MantleLedgeWS, @@ -51,6 +51,9 @@ class ALSV4_CPP_API UALSMantleComponent : public UActorComponent FALSMantleAsset GetMantleAsset(EALSMantleType MantleType, EALSOverlayState CurrentOverlayState); protected: + virtual void TickComponent(float DeltaTime, ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; + // Called when the game starts virtual void BeginPlay() override; @@ -109,4 +112,6 @@ class ALSV4_CPP_API UALSMantleComponent : public UActorComponent private: UPROPERTY() AALSBaseCharacter* OwnerCharacter; + + UALSDebugComponent* DebugComponent = nullptr; }; diff --git a/Source/ALSV4_CPP/Public/Library/ALSMathLibrary.h b/Source/ALSV4_CPP/Public/Library/ALSMathLibrary.h index 211f92b7..cb83c04f 100644 --- a/Source/ALSV4_CPP/Public/Library/ALSMathLibrary.h +++ b/Source/ALSV4_CPP/Public/Library/ALSMathLibrary.h @@ -3,12 +3,14 @@ // License: MIT License (http://www.opensource.org/licenses/mit-license.php) // Source Code: https://github.com/dyanikoglu/ALSV4_CPP // Original Author: Doğa Can Yanıkoğlu -// Contributors: +// Contributors: Achim Turan #pragma once #include "ALSCharacterEnumLibrary.h" + +#include "Kismet/KismetSystemLibrary.h" #include "CoreMinimal.h" #include "Library/ALSCharacterStructLibrary.h" #include "ALSMathLibrary.generated.h" @@ -51,7 +53,7 @@ class ALSV4_CPP_API UALSMathLibrary : public UBlueprintFunctionLibrary UFUNCTION(BlueprintCallable, Category = "ALS|Math Utils") static bool CapsuleHasRoomCheck(UCapsuleComponent* Capsule, FVector TargetLocation, float HeightOffset, - float RadiusOffset); + float RadiusOffset, EDrawDebugTrace::Type DebugType = EDrawDebugTrace::Type::None, bool DrawDebugTrace = false); UFUNCTION(BlueprintCallable, Category = "ALS|Math Utils") static bool AngleInRange(float Angle, float MinAngle, float MaxAngle, float Buffer, bool IncreaseBuffer);