Add new Perception Senses

This commit is contained in:
baz 2024-02-13 21:23:15 +00:00
parent 5b90d26bc6
commit 763706ac5c
5 changed files with 121 additions and 3 deletions

BIN
Content/Enemy/Worker/AIC_Worker.uasset (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -27,8 +27,19 @@ AEnemyAIController::AEnemyAIController(const FObjectInitializer& object_initiali
SightConfig->DetectionByAffiliation.bDetectEnemies = true;
SightConfig->DetectionByAffiliation.bDetectNeutrals = true;
HearingConfig = CreateDefaultSubobject<UAISenseConfig_Hearing>(TEXT("Hearing Sense Config"));
HearingConfig->HearingRange = 800.0f;
HearingConfig->SetMaxAge(3.0f);
HearingConfig->DetectionByAffiliation.bDetectEnemies = true;
HearingConfig->DetectionByAffiliation.bDetectNeutrals = true;
DamageConfig = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("Damage Sense Config"));
DamageConfig->SetMaxAge(5.0f);
AIPerception->SetDominantSense(SightConfig->GetSenseImplementation());
AIPerception->ConfigureSense(*SightConfig);
AIPerception->ConfigureSense(*HearingConfig);
AIPerception->ConfigureSense(*DamageConfig);
}
void AEnemyAIController::OnPossess(APawn* InPawn)
@ -120,7 +131,7 @@ void AEnemyAIController::OnDeath(FDamageInfo info)
void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
{
for (auto actor : actors)
for (AActor* actor : actors)
{
if (!actor->GetClass()->IsChildOf(APlayerCharacter::StaticClass()))
{
@ -130,13 +141,32 @@ void AEnemyAIController::OnPerceptionUpdated(const TArray<AActor*>& actors)
FActorPerceptionBlueprintInfo perceptionInfo;
PerceptionComponent->GetActorsPerception(actor, perceptionInfo);
for (auto& stimulus : perceptionInfo.LastSensedStimuli)
for (FAIStimulus& stimulus : perceptionInfo.LastSensedStimuli)
{
if (!stimulus.IsValid() || stimulus.IsExpired())
if (!stimulus.IsValid() || stimulus.IsExpired() ||
static_cast<EAIState>(Blackboard->GetValueAsEnum("State")) == EAIState::DEAD)
{
continue;
}
FAISenseID SightID = SightConfig->GetSenseID();
FAISenseID HearingID = HearingConfig->GetSenseID();
FAISenseID DamageID = DamageConfig->GetSenseID();
if (stimulus.Type == SightID)
{
SensedSight(actor, stimulus);
}
else if (stimulus.Type == HearingID)
{
SensedHearing(actor, stimulus);
stimulus.StimulusLocation;
}
else if (stimulus.Type == DamageID)
{
SensedDamaged(actor, stimulus);
}
Blackboard->SetValueAsObject("TargetActor", actor);
if (stimulus.IsActive())
@ -199,3 +229,30 @@ void AEnemyAIController::SetStateAsAttacking(AActor* target)
Blackboard->SetValueAsObject("TargetActor", target);
SetState(EAIState::ATTACKING);
}
void AEnemyAIController::SensedSight(AActor* actor, FAIStimulus& stimulus)
{
EAIState CurrentState = static_cast<EAIState>(Blackboard->GetValueAsEnum("State"));
if (CurrentState == EAIState::PASSIVE || CurrentState == EAIState::INVESTIGATING)
{
SetStateAsAttacking(actor);
}
}
void AEnemyAIController::SensedHearing(AActor* actor, FAIStimulus& stimulus)
{
EAIState CurrentState = static_cast<EAIState>(Blackboard->GetValueAsEnum("State"));
if (CurrentState == EAIState::PASSIVE || CurrentState == EAIState::INVESTIGATING)
{
SetState(EAIState::INVESTIGATING);
Blackboard->SetValueAsVector("InvestigationLocation", stimulus.StimulusLocation);
}
}
void AEnemyAIController::SensedDamaged(AActor* actor, FAIStimulus& stimulus)
{
SetStateAsAttacking(actor);
}

View File

@ -7,6 +7,8 @@
#include "EAIState.h"
#include "EnemyCharacter.h"
#include "PlayerCharacter.h"
#include "Perception/AISenseConfig_Damage.h"
#include "Perception/AISenseConfig_Hearing.h"
#include "Perception/AISenseConfig_Sight.h"
#include "EnemyAIController.generated.h"
@ -30,6 +32,10 @@ private:
UAISenseConfig_Sight* SightConfig;
UAISenseConfig_Hearing* HearingConfig;
UAISenseConfig_Damage* DamageConfig;
bool HasAttackToken = false;
public:
@ -69,4 +75,12 @@ public:
UFUNCTION()
void SetStateAsAttacking(AActor* target);
private:
void SensedSight(AActor* actor, FAIStimulus& stimulus);
void SensedHearing(AActor* actor, FAIStimulus& stimulus);
void SensedDamaged(AActor* actor, FAIStimulus& stimulus);
};

View File

@ -0,0 +1,17 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "../Tasks/BTTSetState.h"
#include "Nakatomi/EnemyAIController.h"
EBTNodeResult::Type UBTTSetState::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory)
{
if (AEnemyAIController* EnemyController = Cast<AEnemyAIController>(owner.GetAIOwner()))
{
EnemyController->SetState(NewState);
return EBTNodeResult::Succeeded;
}
return EBTNodeResult::Failed;
}

View File

@ -0,0 +1,27 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/BTTaskNode.h"
#include "Nakatomi/EAIState.h"
#include "BTTSetState.generated.h"
/**
*
*/
UCLASS()
class NAKATOMI_API UBTTSetState : public UBTTaskNode
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = "Options",
Meta = (AllowPrivateAccess = "true", DisplayName = "New State"))
EAIState NewState;
public:
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override;
};