I have been having trouble with getting my AI to act properly its like the line of sight is not acting how it should, Although when I debug the AI controller the peripheral visions line look proper, the problem happens it still notices me even if angle is 0.000 and behind the AI when It should not see me.
As you Can See by this image the green debug lines is drawing the periphal vision
But as soon as I even step out of cover it automatically progress to the next event in the behaviour tree like it has vision on me.
I don’t understand if my behaviour tree is set up properly but it looks like it is.
This is the code and how I set it up.
The ShooterAIController:
// Fill out your copyright notice in the Description page of Project Settings.
#include "ShooterAIController.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISense_Sight.h"
#include "ShooterCharacter.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Perception/AISenseConfig_Sight.h"
AShooterAIController::AShooterAIController()
{
// Create and configure the sight sense
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("SightConfig"));
SightConfig->SightRadius = 2000.0f;
SightConfig->LoseSightRadius = SightConfig->SightRadius + 500.0f;
SightConfig->PeripheralVisionAngleDegrees = 60.0f;
SightConfig->SetMaxAge(5.0f);
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
SightConfig->DetectionByAffiliation.bDetectFriendlies = true;
// Access and configure the perception component
PerceptionComponent = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("PerceptionComponent"));
PerceptionComponent->ConfigureSense(*SightConfig);
PerceptionComponent->SetDominantSense(*SightConfig->GetSenseImplementation());
PerceptionComponent->OnPerceptionUpdated.AddDynamic(this, &AShooterAIController::OnPerceptionUpdated);
}
void AShooterAIController::BeginPlay()
{
Super::BeginPlay();
if (AIBehavior != nullptr)
{
RunBehaviorTree(AIBehavior);
GetBlackboardComponent()->SetValueAsVector(TEXT("StartLocation"), GetPawn()->GetActorLocation());
}
}
void AShooterAIController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
}
bool AShooterAIController::isDead() const
{
AShooterCharacter* ControlledCharacter = Cast<AShooterCharacter>(GetPawn());
if (ControlledCharacter != nullptr)
{
return ControlledCharacter->IsDead();
}
return true;
}
void AShooterAIController::OnPerceptionUpdated(const TArray<AActor*>& UpdatedActors)
{
AShooterCharacter* ControlledCharacter = Cast<AShooterCharacter>(GetPawn());
if (ControlledCharacter == nullptr)
{
return;
}
bool bCanSeePlayer = false;
for (AActor* Actor : UpdatedActors)
{
if (Actor->IsA(APawn::StaticClass()))
{
APawn* SensedPawn = Cast<APawn>(Actor);
if (SensedPawn)
{
FVector ToPlayer = SensedPawn->GetActorLocation() - ControlledCharacter->GetActorLocation();
ToPlayer.Normalize();
FVector Forward = ControlledCharacter->GetActorForwardVector();
Forward.Normalize();
float DotProduct = FVector::DotProduct(Forward, ToPlayer);
float Angle = FMath::Acos(DotProduct) * (180.0f / PI);
UE_LOG(LogTemp, Warning, TEXT("Angle to Player: %f"), Angle);
if (Angle <= SightConfig->PeripheralVisionAngleDegrees / 2)
{
if (LineOfSightTo(SensedPawn))
{
UE_LOG(LogTemp, Warning, TEXT("Player in sight!"));
bCanSeePlayer = true;
GetBlackboardComponent()->SetValueAsVector("PlayerLocation", SensedPawn->GetActorLocation());
DrawDebugLine(GetWorld(), ControlledCharacter->GetActorLocation(), SensedPawn->GetActorLocation(), FColor::Green, false, 1.0f, 0, 2.0f);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Player not in line of sight."));
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Player out of peripheral vision range."));
}
}
}
}
if (!bCanSeePlayer)
{
UE_LOG(LogTemp, Warning, TEXT("No player detected."));
GetBlackboardComponent()->ClearValue("PlayerLocation");
}
}
Playerlocationifseen
// Fill out your copyright notice in the Description page of Project Settings.
#include "BTService_PlayerLocationIfSeen.h"
#include "ShooterAIController.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Kismet/GameplayStatics.h"
#include "AIController.h"
UBTService_PlayerLocationIfSeen::UBTService_PlayerLocationIfSeen()
{
NodeName = TEXT("Player Location If Seen");
}
void UBTService_PlayerLocationIfSeen::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(),0);
if(PlayerPawn == nullptr)
{
return;
}
if(OwnerComp.GetAIOwner() == nullptr)
{
return;;
}
if(OwnerComp.GetAIOwner()->LineOfSightTo(PlayerPawn))
{
OwnerComp.GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(),PlayerPawn->GetActorLocation());
}
else
{
OwnerComp.GetBlackboardComponent()->ClearValue(GetSelectedBlackboardKey());
}
}
If anyone could help I have been staring at this for a while and cant understand why the AI is working the wrong way.