[박치영] Ai Perception 작업

main
PCYPC\pcy35 2023-08-29 20:35:20 +09:00
parent c42582a55c
commit 418e5a08b7
11 changed files with 135 additions and 9 deletions

View File

@ -3,10 +3,34 @@
#include "AI/CombatAIController.h"
#include "GameplayTagAssetInterface.h"
#include "MasterAI.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Damage.h"
#include "Perception/AISenseConfig_Sight.h"
ACombatAIController::ACombatAIController()
{
PerceptionComponent = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("PerceptionComponent"));
SightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("SightConfig"));
SightConfig->SightRadius = 3000.f;
SightConfig->LoseSightRadius = 3500.f;
SightConfig->PeripheralVisionAngleDegrees = 45.f;
FAISenseAffiliationFilter AffiliationFilter;
AffiliationFilter.bDetectEnemies = true;
AffiliationFilter.bDetectFriendlies = true;
AffiliationFilter.bDetectNeutrals = true;
SightConfig->DetectionByAffiliation = AffiliationFilter;
SightConfig->AutoSuccessRangeFromLastSeenLocation = 500.f;
PerceptionComponent->ConfigureSense(*SightConfig);
DamageConfig = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("DamageConfig"));
DamageConfig->SetMaxAge(3.f); // Expired 3 Seconds
PerceptionComponent->ConfigureSense(*DamageConfig);
PerceptionComponent->OnPerceptionUpdated.AddDynamic(this, &ACombatAIController::OnUpdatePerception);
}
void ACombatAIController::OnPossess(APawn* InPawn)
@ -20,3 +44,40 @@ void ACombatAIController::OnPossess(APawn* InPawn)
RunBehaviorTree(MasterAI->GetBeHaviorTree());
}
}
void ACombatAIController::OnUpdatePerception(const TArray<AActor*>& PerceivedActors)
{
for (auto SensoredActor : PerceivedActors)
{
FActorPerceptionBlueprintInfo PerceptionInfo;
GetPerceptionComponent()->GetActorsPerception(SensoredActor, PerceptionInfo);
for(int i = 0; i < PerceptionInfo.LastSensedStimuli.Num(); i++)
{
auto Info = PerceptionInfo.LastSensedStimuli[i];
auto SensedClass = UAIPerceptionSystem::GetSenseClassForStimulus(this, Info);
if(SensedClass == UAISense_Sight::StaticClass())
{
if(Info.WasSuccessfullySensed())
{
if(Cast<IGameplayTagAssetInterface>(SensoredActor)->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
{
Blackboard->SetValueAsObject(TEXT("Target"), SensoredActor);
}
}
else
Blackboard->SetValueAsObject(TEXT("Target"), nullptr);
}
else if(SensedClass == UAISense_Damage::StaticClass())
{
if(Info.WasSuccessfullySensed() && !Info.IsExpired()) //After DamageConfig->GetMaxAge then Expired
{
if(Cast<IGameplayTagAssetInterface>(SensoredActor)->HasMatchingGameplayTag(FCombatGameplayTags::Get().Character_Player))
{
Blackboard->SetValueAsObject(TEXT("Target"), SensoredActor);
}
}
}
}
}
}

View File

@ -16,9 +16,16 @@ class D1_API ACombatAIController : public AAIController
public:
ACombatAIController();
protected:
protected: //Inherited Func
virtual void OnPossess(APawn* InPawn) override;
public: //Delegate Func
UFUNCTION(BlueprintCallable)
void OnUpdatePerception(const TArray<AActor*>& PerceivedActors);
private:
UPROPERTY()
TObjectPtr<class AMasterAI> MasterAI;
UPROPERTY()
TObjectPtr<class UAISenseConfig_Sight> SightConfig;
UPROPERTY()
TObjectPtr<class UAISenseConfig_Damage> DamageConfig;
};

View File

@ -16,6 +16,7 @@
#include "DamageType/AttackDamageType.h"
#include "Kismet/KismetMathLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "Perception/AISense_Damage.h"
AMasterAI::AMasterAI()
{
@ -98,12 +99,16 @@ float AMasterAI::TakeDamage(float Damage, FDamageEvent const& DamageEvent, ACont
if (DamageEvent.IsOfType(FPointDamageEvent::ClassID))
{
const FPointDamageEvent* PointDamageEvent = static_cast<const FPointDamageEvent*>(&DamageEvent);
APawn* Attacker = EventInstigator->GetPawn();
//스텟 관련 처리
StatsComponent->TakeDamageOnStat(Damage);
//데미지 관련 AI 처리
UAISense_Damage::ReportDamageEvent(GetWorld(), this, Attacker, Damage, PointDamageEvent->HitInfo.Location, PointDamageEvent->HitInfo.Location);
//앞에서 맞았는지 뒤에서 맞았는지 판별
bHitFront = UKismetMathLibrary::InRange_FloatFloat(this->GetDotProductTo(EventInstigator->GetPawn()), -0.1f, 1.f);
bHitFront = UKismetMathLibrary::InRange_FloatFloat(this->GetDotProductTo(Attacker), -0.1f, 1.f);
LastHitInfo = PointDamageEvent->HitInfo;
//play sound, effect

View File

@ -92,8 +92,12 @@ ACombatCharacter::ACombatCharacter()
JoggingSpeed = 500.f;
SprintSpeed = 700.f;
//Settings OwnedGameplayTags
OwnedGameplayTags.AddTag(FCombatGameplayTags::Get().Character_Player);
ChargeAttackTime = 0.18f;
PelvisBoneName = TEXT("pelvis");
}
void ACombatCharacter::BeginPlay()

View File

@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagAssetInterface.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "InputAction.h"
@ -11,11 +12,12 @@
#include "Components/StatsComponent.h"
#include "Components/TargetingComponent.h"
#include "Definitions/GameEnums.h"
#include "Interface/CombatGameplayTag.h"
#include "CombatCharacter.generated.h"
UCLASS(config=Game)
class ACombatCharacter : public ACharacter, public ICombatInterface
class ACombatCharacter : public ACharacter, public ICombatInterface, public IGameplayTagAssetInterface
{
GENERATED_BODY()
@ -108,7 +110,9 @@ public:
virtual void SetCanMove_Implementation(bool inputCanMove) override;
virtual EMovementSpeedMode GetCombatMovementSpeedMode() override { return GetMovementSpeedMode(); }
// Inherited via IGameplayTagAssetInterface
virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override { TagContainer = OwnedGameplayTags; }
public:
void SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode);
FORCEINLINE EMovementSpeedMode GetMovementSpeedMode() const { return MovementSpeedMode; }
@ -206,12 +210,13 @@ public:
private:
FTimerHandle StaminaTimerHandle;
private:
bool IsHeavyAttack;
float AttackHeldTime;
bool bAttackCharged;
bool bCanMove = true;
bool bHitFront;
FHitResult LastHitInfo;
FHitResult LastHitInfo;
FGameplayTagContainer OwnedGameplayTags;
};

View File

@ -8,8 +8,16 @@ FCombatGameplayTags FCombatGameplayTags::GameplayTags;
void FCombatGameplayTags::InitializeNativeGameplayTags()
{
if(GameplayTags.Character_State_Attacking.IsValid()) //Already Execute? then Do not Execute
if(GameplayTags.Character_Player.IsValid()) //Already Execute? then Do not Execute
return;
/**
* Player
*/
GameplayTags.Character_Player = UGameplayTagsManager::Get().AddNativeGameplayTag(
FName("Character.Player"),
FString("Player")
);
/**
* State

View File

@ -12,6 +12,9 @@ public:
static void InitializeNativeGameplayTags();
public:
//Character
FGameplayTag Character_Player;
//State
FGameplayTag Character_State_Attacking;
FGameplayTag Character_State_Dead;

View File

@ -0,0 +1,6 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interface/CombatGameplayTag.h"
// Add default functionality here for any ICombatGameplayTag functions that are not pure virtual.

View File

@ -0,0 +1,27 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "UObject/Interface.h"
#include "CombatGameplayTag.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UCombatGameplayTag : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class D1_API ICombatGameplayTag
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual FGameplayTagContainer GetOwnedGameplayTag() = 0;
};