Help, I'm stuck and I have an issue on my Wheeled Vehicle prototype

Hello guys!

I’m prototyping a race game and I was looking for a way to reduce the steer angle, using C++.

In this code, I have a angle value, called AxisDeviation, to define a MoveForward range.



// Fill out your copyright notice in the Description page of Project Settings.


#include "MoveForwardTask.h"
#include "GameFramework/Pawn.h"
#include "BehaviorTree/BehaviorTreeTypes.h"
#include "BehaviorTree/BehaviorTreeComponent.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "BehaviorTree/Blackboard/BlackboardKeyType_Vector.h"
#include "UObject/UObjectGlobals.h"
#include "CarAIController.h"
#include "NPCCarPawn.h"
#include "Blackboard_keys.h"
#include "Components/SplineComponent.h"
#include "Components/SplineMeshComponent.h"
#include "SplineActor.h"
#include "Kismet/KismetMathLibrary.h"
#include "WheeledVehicleMovementComponent.h"
#include "DrawDebugHelpers.h"
#include "Engine/GameEngine.h"
#include "WheeledVehicleMovementComponent4W.h"

UMoveForwardTask::UMoveForwardTask(const FObjectInitializer& ObjectInitializer)
{ NodeName = TEXT("Move Forward");
 
 
}


EBTNodeResult::Type UMoveForwardTask::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{ const ACarAIController* CarController = Cast<ACarAIController>(OwnerComp.GetAIOwner());
ANPCCarPawn* CarPawn = Cast<ANPCCarPawn>(CarController->GetPawn());
FVector ClosestPoint = CarPawn->GetTrackCircuit()->GetSplineComponent()->FindLocationClosestToWorldLocation(CarPawn->GetActorLocation(), ESplineCoordinateSpace::World);
DrawDebugLine(GetWorld(), CarPawn->GetActorLocation(), ClosestPoint, FColor::Red, false, 180.f, 3.f);
ASplineActor* CurrentTrack = CarPawn->GetTrackCircuit();

float LineTraceLength = 300.f;

FVector LeftTraceStart, MiddleTraceStart, RightTraceStart;
FVector LeftTraceEnd, MiddleTraceEnd, RightTraceEnd;

LeftTraceStart = MiddleTraceStart = RightTraceStart = CarPawn->GetActorLocation() + FVector(0.f, 0.f, 25.f);
LeftTraceEnd = LeftTraceStart + (CarPawn->GetActorForwardVector().ToOrientationRotator() + FRotator(-6.f, -22.5f, 0.f)).Vector() * LineTraceLength;
MiddleTraceEnd = MiddleTraceStart + (CarPawn->GetActorForwardVector().ToOrientationRotator() + FRotator(-6.f, 0.f, 0.f)).Vector() * LineTraceLength;
RightTraceEnd = RightTraceStart + (CarPawn->GetActorForwardVector().ToOrientationRotator() + FRotator(-6.f, 22.5f, 0.f)).Vector() * LineTraceLength;

FCollisionQueryParams TraceParams(TEXT("Circuit Trace"), true, CarPawn);
TraceParams.bTraceComplex = true;
TraceParams.bReturnPhysicalMaterial = true;
TArray<ASplineActor*> TrackCircuitArr = CarPawn->GetTrackCircuitArray();
for(int Index = 0; Index < TrackCircuitArr.Num(); Index++){
  [INDENT=2]if(TrackCircuitArr[Index] != CurrentTrack)
{[/INDENT]
  [INDENT=3]TraceParams.AddIgnoredActor(TrackCircuitArr[Index]);[/INDENT]
  [INDENT=2]}[/INDENT]
  }

FHitResult LeftTraceHitDetails = FHitResult(ForceInit);
FHitResult MiddleTraceHitDetails = FHitResult(ForceInit);
FHitResult RightTraceHitDetails = FHitResult(ForceInit);

bool bLeftTraceStroke = CarPawn->GetWorld()->LineTraceSingleByChannel(
  [INDENT=2]LeftTraceHitDetails,
LeftTraceStart,
LeftTraceEnd,
ECC_WorldStatic,
TraceParams[/INDENT]
  );

bool bMiddleTraceStroke = CarPawn->GetWorld()->LineTraceSingleByChannel(
  [INDENT=2]MiddleTraceHitDetails,
MiddleTraceStart,
MiddleTraceEnd,
ECC_WorldStatic,
TraceParams[/INDENT]
  );

bool bRightTraceStroke = CarPawn->GetWorld()->LineTraceSingleByChannel(
  [INDENT=2]RightTraceHitDetails,
RightTraceStart,
RightTraceEnd,
ECC_WorldStatic,
TraceParams[/INDENT]
  );

if(bLeftTraceStroke)
{
  [INDENT=2]DrawDebugLine(CarPawn->GetWorld(), LeftTraceStart, LeftTraceEnd, FColor::Orange,
false, .05f, ECC_WorldStatic, 2.5f);
DrawDebugPoint(CarPawn->GetWorld(), LeftTraceHitDetails.ImpactPoint, 50.f, FColor::
Green, false, .05f, ECC_WorldStatic);
UE_LOG(LogTemp, Warning, TEXT("Actor hit by the left trace: %s"), *LeftTraceHitDetails.Actor->GetName());[/INDENT]
  }
if (bMiddleTraceStroke)
{
  [INDENT=2]DrawDebugLine(CarPawn->GetWorld(), MiddleTraceStart, MiddleTraceEnd, FColor::Orange,
false, .05f, ECC_WorldStatic, 2.5f);
DrawDebugPoint(CarPawn->GetWorld(), MiddleTraceHitDetails.ImpactPoint, 50.f, FColor::
Green, false, .05f, ECC_WorldStatic);
UE_LOG(LogTemp, Warning, TEXT("Actor hit by the middle trace: %s"), *MiddleTraceHitDetails.Actor->GetName());[/INDENT]
  }
if (bRightTraceStroke)
{
  [INDENT=2]DrawDebugLine(CarPawn->GetWorld(), RightTraceStart, RightTraceEnd, FColor::Orange,
false, .05f, ECC_WorldStatic, 2.5f);
DrawDebugPoint(CarPawn->GetWorld(), RightTraceHitDetails.ImpactPoint, 50.f, FColor::
Green, false, .05f, ECC_WorldStatic);
UE_LOG(LogTemp, Warning, TEXT("Actor hit by the right trace: %s"), *RightTraceHitDetails.Actor->GetName());[/INDENT]
  }

if(CarPawn->CanMove())
{
  [INDENT=2]//ASplineActor* CurrentTrack = CarPawn->GetTrackCircuit();
float angle = CarPawn->CalculateAngleBetween();
if (CarPawn->IsTravellingReverseMode())
{[/INDENT]
  [INDENT=3]angle = angle - 180.f;[/INDENT]
  [INDENT=2]}
float AxisDeviation = CarPawn->GetAxisDeviation();

//UWheeledVehicleMovementComponent4W* Vehicle4W = CastChecked<UWheeledVehicleMovementComponent4W>(CarPawn->GetVehicleMovement());
//Vehicle4W->Wheels[0].SteerAngle = 15.f;

/*
if(GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Orange, FString::Printf(TEXT("Angle = %f"), angle));
}
*/

UE_LOG(LogTemp, Warning, TEXT("Angle = %s"), *FString::Printf(TEXT("%f"), angle));
if ([/INDENT]
  [INDENT=3]((angle >= -AxisDeviation && angle <= AxisDeviation) ||
(angle >= (180 - AxisDeviation) || angle <= (-180 + AxisDeviation))) &&
(LeftTraceHitDetails.Actor == CurrentTrack &&
MiddleTraceHitDetails.Actor == CurrentTrack &&
RightTraceHitDetails.Actor == CurrentTrack)[/INDENT]
  [INDENT=2])
{[/INDENT]
  [INDENT=3]CarPawn->MoveForward(1);
UE_LOG(LogTemp, Warning, TEXT("MOVING FORWARD"));[/INDENT]
  [INDENT=2]}
else
{[/INDENT]
  [INDENT=3]if([/INDENT]
  [INDENT=4](LeftTraceHitDetails.Actor != CurrentTrack &&[/INDENT]
  [INDENT=4]MiddleTraceHitDetails.Actor == CurrentTrack &&
RightTraceHitDetails.Actor == CurrentTrack) ||
(LeftTraceHitDetails.Actor != CurrentTrack &&
MiddleTraceHitDetails.Actor != CurrentTrack &&
RightTraceHitDetails.Actor == CurrentTrack) ||
(LeftTraceHitDetails.Actor == CurrentTrack &&
MiddleTraceHitDetails.Actor == CurrentTrack &&
RightTraceHitDetails.Actor == CurrentTrack &&
(angle > AxisDeviation && angle < (180 - AxisDeviation)) )[/INDENT]
  [INDENT=3])
{[/INDENT]
  [INDENT=4]CarPawn->MoveRight(1);
UE_LOG(LogTemp, Warning, TEXT("MOVING RIGHT"));[/INDENT]
  [INDENT=3]}
else
{[/INDENT]
  [INDENT=4]if ([/INDENT]
  [INDENT=5](LeftTraceHitDetails.Actor == CurrentTrack &&
MiddleTraceHitDetails.Actor == CurrentTrack &&
RightTraceHitDetails.Actor != CurrentTrack) ||
(LeftTraceHitDetails.Actor == CurrentTrack &&
MiddleTraceHitDetails.Actor != CurrentTrack &&
RightTraceHitDetails.Actor != CurrentTrack) ||
(LeftTraceHitDetails.Actor == CurrentTrack &&
MiddleTraceHitDetails.Actor == CurrentTrack &&
RightTraceHitDetails.Actor == CurrentTrack &&
(angle < -AxisDeviation && angle > (-180 + AxisDeviation)))[/INDENT]
  [INDENT=4])
{[/INDENT]
  [INDENT=5]CarPawn->MoveRight(-1);
UE_LOG(LogTemp, Warning, TEXT("MOVING LEFT"));[/INDENT]
  [INDENT=4]}[/INDENT]
  [INDENT=3]}[/INDENT]
  [INDENT=2]}[/INDENT]
  }

FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);

return EBTNodeResult::Succeeded;
 
 }




Here is the video:

How can I reduce both the steer angle and the steer rotation rate, to solve the problem found in this video?

A guy on Reddit told me to find a InputSteerRiseRate variable inside the UWheeledVehicleMovementComponent. I didn’t find a InputSteerRiseRate variable or a InputSteerFallRate, but I did find instead a FVehicvleInputRate called SteeringInputRate, that contains floats called RiseRate and FallRate, but it’s a protected variable and there is no Getter to access it. There is another way?

He also told me that the SteerAngle is inside the UVehicleWheel (indeed), but I should avoid it, otherwise I have to recalculate the ackermann angle. I was looking for the ackermann angle, but I didn’t find it inside the engine code. Any clues?

Any help will be appreciated!

Thanks! :smiley:

Just a little bump