Add EQS for AI to Find Valid Cover Locations

This commit is contained in:
Philip W 2023-09-29 00:07:12 +01:00
parent f10fda5142
commit d4c602e262
14 changed files with 233 additions and 7 deletions

Binary file not shown.

Binary file not shown.

BIN
EndlessVendetta/Content/AI/Enemy/Basic/EQSB_Player.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/AI/Enemy/Basic/EQS_FindCover.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
EndlessVendetta/Content/AI/Enemy/Basic/EQS_Test.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,32 @@
[/Script/HoloLensPlatformEditor.HoloLensTargetSettings]
bBuildForEmulation=False
bBuildForDevice=True
bUseNameForLogo=True
bBuildForRetailWindowsStore=False
bAutoIncrementVersion=False
bShouldCreateAppInstaller=False
AppInstallerInstallationURL=
HoursBetweenUpdateChecks=0
bEnablePIXProfiling=False
TileBackgroundColor=(B=64,G=0,R=0,A=255)
SplashScreenBackgroundColor=(B=64,G=0,R=0,A=255)
+PerCultureResources=(CultureId="",Strings=(PackageDisplayName="",PublisherDisplayName="",PackageDescription="",ApplicationDisplayName="",ApplicationDescription=""),Images=())
TargetDeviceFamily=Windows.Holographic
MinimumPlatformVersion=
MaximumPlatformVersionTested=10.0.18362.0
MaxTrianglesPerCubicMeter=500.000000
SpatialMeshingVolumeSize=20.000000
CompilerVersion=Default
Windows10SDKVersion=10.0.18362.0
+CapabilityList=internetClientServer
+CapabilityList=privateNetworkClientServer
+Uap2CapabilityList=spatialPerception
bSetDefaultCapabilities=False
SpatializationPlugin=
SourceDataOverridePlugin=
ReverbPlugin=
OcclusionPlugin=
SoundCueCookQualityIndex=-1

View File

@ -0,0 +1,83 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "AI_EnemyController.h"
#include "EnemyCharacter.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Sight.h"
// Sets default values
AAI_EnemyController::AAI_EnemyController(FObjectInitializer const& ObjectInitializer)
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SetupPerceptionSystem();
}
// Called when the game starts or when spawned
void AAI_EnemyController::BeginPlay()
{
Super::BeginPlay();
}
void AAI_EnemyController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
if (const AEnemyCharacter* EnemyCharacter = Cast<AEnemyCharacter>(InPawn))
{
if (UBehaviorTree* const BehaviorTree = EnemyCharacter->GetBehaviorTree())
{
UBlackboardComponent* TempBlackboardPtr;
UseBlackboard(BehaviorTree->BlackboardAsset, TempBlackboardPtr);
Blackboard = TempBlackboardPtr;
RunBehaviorTree(BehaviorTree);
}
}
}
// Called every frame
void AAI_EnemyController::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AAI_EnemyController::SetupPerceptionSystem()
{
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("Sight Config"));
if (IsValid(SightConfig))
{
SetPerceptionComponent(*CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("Perception Component")));
SightConfig->SightRadius = 1000.0f;
SightConfig->LoseSightRadius = 1100.0f;
SightConfig->PeripheralVisionAngleDegrees = 90.0f;
SightConfig->SetMaxAge(5.0f);
SightConfig->AutoSuccessRangeFromLastSeenLocation = 520.0f;
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
SightConfig->DetectionByAffiliation.bDetectFriendlies = true;
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
GetPerceptionComponent()->SetDominantSense(*SightConfig->GetSenseImplementation());
GetPerceptionComponent()->OnTargetPerceptionUpdated.AddDynamic(this, &AAI_EnemyController::OnTargetPerceptionUpdated);
GetPerceptionComponent()->ConfigureSense(*SightConfig);
}
}
void AAI_EnemyController::OnTargetPerceptionUpdated(AActor* Actor, FAIStimulus const Stimulus)
{
if (AEnemyCharacter* const EnemyCharacter = Cast<AEnemyCharacter>(Actor))
{
if (Stimulus.WasSuccessfullySensed())
{
GetBlackboardComponent()->SetValueAsObject("TargetActor", Actor);
GetBlackboardComponent()->SetValueAsVector("TargetLocation", Stimulus.StimulusLocation);
}
else
{
GetBlackboardComponent()->ClearValue("TargetActor");
GetBlackboardComponent()->ClearValue("TargetLocation");
}
}
}

View File

@ -0,0 +1,35 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AIController.h"
#include "Perception/AIPerceptionTypes.h"
#include "AI_EnemyController.generated.h"
UCLASS()
class ENDLESSVENDETTA_API AAI_EnemyController : public AAIController
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
explicit AAI_EnemyController(FObjectInitializer const& ObjectInitializer);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void OnPossess(APawn* InPawn) override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
class UAISenseConfig_Sight* SightConfig;
void SetupPerceptionSystem();
UFUNCTION()
void OnTargetPerceptionUpdated(AActor* Actor, FAIStimulus const Stimulus);
};

View File

@ -0,0 +1,14 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "BTTask_FindCover.h"
UBTTask_FindCover::UBTTask_FindCover(FObjectInitializer const& ObjectInitializer)
{
NodeName = TEXT("Find Vaild Cover");
}
EBTNodeResult::Type UBTTask_FindCover::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
return EBTNodeResult::Failed;
}

View File

@ -0,0 +1,23 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_FindCover.generated.h"
/**
*
*/
UCLASS()
class ENDLESSVENDETTA_API UBTTask_FindCover : public UBTTask_BlackboardBase
{
GENERATED_BODY()
public:
explicit UBTTask_FindCover(FObjectInitializer const& ObjectInitializer);
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
private:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true"))
float SearchRadius = 1000.f;
};

View File

@ -3,12 +3,17 @@
#include "EnemyCharacter.h"
#include "Perception/AIPerceptionStimuliSourceComponent.h"
#include "Perception/AISense_Sight.h"
class UAISense_Sight;
// Sets default values
AEnemyCharacter::AEnemyCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SetupStimuliSourceComponent();
}
// Called when the game starts or when spawned
@ -30,3 +35,18 @@ void AEnemyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComp
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
UBehaviorTree* AEnemyCharacter::GetBehaviorTree() const
{
return BehaviorTree;
}
void AEnemyCharacter::SetupStimuliSourceComponent()
{
StimuliSourceComponent = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(TEXT("Stimuli Source Component"));
if (IsValid(StimuliSourceComponent))
{
StimuliSourceComponent->RegisterForSense(TSubclassOf<UAISense_Sight>());
StimuliSourceComponent->RegisterWithPerceptionSystem();
}
}

View File

@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/BehaviorTree.h"
#include "GameFramework/Character.h"
#include "EnemyCharacter.generated.h"
@ -19,10 +20,19 @@ protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI")
UBehaviorTree* BehaviorTree;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UFUNCTION(BlueprintCallable, Category = "AI")
UBehaviorTree* GetBehaviorTree() const;
private:
class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent;
void SetupStimuliSourceComponent();
};