포트폴리오 제작/Project_P
Project_P AI Perception Damage Sense 적용
k99812
2025. 5. 30. 16:46
Damage Sense
기존 몬스터 AI는 몬스터 뒤로 몰래 다가가 때려도 바보처럼 맞기만 했다.
그래서 AI Perception에서 제공하는 Damage Sense를 활용하여 몬스터가 공격당하면
플레이어를 감지할 수 있도록구현 해보았다.
Damage Sense 생성
APPAIController 헤더파일
virtual void PerceptionSensedDamage(APawn* Pawn_);
UPROPERTY(VisibleAnywhere)
TObjectPtr<class UAISenseConfig_Damage> SenseConfig_Damage;
- virtual void PerceptionSensedDamage(APawn* Pawn_);
- ActorPerceptionUpdated 함수에 들어온 FAIStimulus이 Dmage일경우
실행할 함수
- ActorPerceptionUpdated 함수에 들어온 FAIStimulus이 Dmage일경우
- TObjectPtr<class UAISenseConfig_Damage> SenseConfig_Damage;
- 데미지 센스를 저장할 변수
APPAIController Cpp파일
생성자
SenseConfig_Damage = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("SenseConfig_Damage"));
SenseConfig_Damage->SetMaxAge(GruntAIData->AISenseAge);
AIPerceptionComp->ConfigureSense(*SenseConfig_Damage);
- SenseConfig_Damage = CreateDefaultSubobject<UAISenseConfig_Damage>(TEXT("SenseConfig_Damage"));
- 데미지 센스 생성
- SenseConfig_Damage->SetMaxAge(GruntAIData->AISenseAge);
- 데미지 센스 정보의 유효시간 설정
- AIPerceptionComp->ConfigureSense(*SenseConfig_Damage);
- AIPerceptionComp에 생성한 데미지 센스를 등록
ActorPerceptionUpdated
void APPAIController::ActorPerceptionUpdated(AActor* Actor, FAIStimulus Stimulus)
{
APawn* PerceptionedPawn = Cast<APawn>(Actor);
if (PerceptionedPawn && PerceptionedPawn->GetController()->IsPlayerController())
{
TSubclassOf<UAISense> SensedStimulsClass = UAIPerceptionSystem::GetSenseClassForStimulus(this, Stimulus);
~~~
if (SensedStimulsClass == UAISense_Damage::StaticClass())
{
PerceptionSensedDamage(PerceptionedPawn);
}
}
}
- if (SensedStimulsClass == UAISense_Damage::StaticClass())
{
PerceptionSensedDamage(PerceptionedPawn);
}- Stimulus가 Damage이면 PerceptionSensedDamage함수 실행하여 감지된 액터를 넘겨줌
PerceptionSensedDamage
void APPAIController::PerceptionSensedDamage(APawn* PerceptionedPawn)
{
UE_LOG(LogTemp, Log, TEXT("Perception Sensed by Damage : %s"), *PerceptionedPawn->GetName())
if (IsValid(PerceptionedPawn))
{
GetBlackboardComponent()->SetValueAsObject(BBKEY_TARGET, PerceptionedPawn);
AActor::SetActorTickEnabled(true);
FindTargetDelegate.ExecuteIfBound(true);
}
}
- GetBlackboardComponent()->SetValueAsObject(BBKEY_TARGET, PerceptionedPawn);
- 블랙보드의 Target을 감지된 액터로 지정
데미지 이벤트 발생
class UAISense_Damage : public UAISense
{
static AIMODULE_API void ReportDamageEvent(~~~);
}
데미지 이벤트를 발생시키려면 UAISense_Damage 클래스에 있는 static 함수 ReportDamageEvent함수를 호출해야 된다
해당 함수에선 매개변수로 타격받은 액터, 가해 액터가 필요해 이 둘을 쉽게 얻을 수 있는 AttackHitCheck GA에서 호출을 하였다
UPPGA_AttackHitCheck Cpp
TraceResultCallback
void UPPGA_AttackHitCheck::TraceResultCallback(const FGameplayAbilityTargetDataHandle& DataHandle)
{
//#include "AbilitySystemBlueprintLibrary.h" 추가
if (UAbilitySystemBlueprintLibrary::TargetDataHasHitResult(DataHandle, 0))
{
FHitResult HitResult = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(DataHandle, 0);
UAbilitySystemComponent* OwnerASC = GetAbilitySystemComponentFromActorInfo_Checked();
UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(HitResult.GetActor());
~~~
//타겟이 몬스터일 경우 AI 데미지 센스 발동
IGameplayTagAssetInterface* TargetActor = Cast<IGameplayTagAssetInterface>(HitResult.GetActor());
if (TargetActor && TargetActor->HasMatchingGameplayTag(PPTAG_CHARACTER_MONSTER))
{
UAISense_Damage::ReportDamageEvent(this, HitResult.GetActor(), OwnerASC->GetAvatarActor(),
OwnerAttributeSet->GetAttackRate(), HitResult.GetActor()->GetActorLocation(), HitResult.Location);
}
}
~~~
}
이 프로젝트에선 몬스터에 GameplayTag를 생성해 몬스터인지 캐릭터인지 태그를 부착했다.
언리얼 엔진에선 GAS 객체가 아니여도 GameplayTag를 손쉽게 사용할 수 있도록 IGameplayTagAssetInterface를 제공한다
- IGameplayTagAssetInterface* TargetActor = Cast<IGameplayTagAssetInterface>(HitResult.GetActor());
- IGameplayTagAssetInterface로 캐스팅
- if (TargetActor && TargetActor->HasMatchingGameplayTag(PPTAG_CHARACTER_MONSTER))
- 캐스팅이 성공 하고
- 타겟액터에 몬스터 태그가 부착되어 있으면
- PPTAG_CHARACTER_MONSTER
FGameplayTag::RequestGameplayTag(FName("Character.Monster"))
- UAISense_Damage::ReportDamageEvent(this, HitResult.GetActor(), OwnerASC->GetAvatarActor(),
OwnerAttributeSet->GetAttackRate(), HitResult.GetActor()->GetActorLocation(), HitResult.Location);- UAISense_Damage::ReportDamageEvent를 호출해 데미지 이벤트를 발생시킨다
적용 영상