1. PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
PostGameplayEffectExecute
위의 함수는 게임플레이 이펙트가 적용되고 난 후 추가적인 작업을 할 때 사용하는 함수이다.
예를 들어 체력이 0이 되면 캐릭터를 데스 상태로 변환하는 등의 작업을 할 수 있다.
매개변수 FGameplayEffectModCallbackData
- EvaluatedData: 변경된 Attribute와 그 값.
- Target: 효과를 적용받는 대상.
- Source: 효과를 유발한 원인(예: 공격자).
- EffectSpec: 실행된 GameplayEffect의 상세 정보
- PostGameplayEffectExecute 함수의 매개변수로 전달되는 FGameplayEffectModCallbackData는 다음과 같은 정보를 포함합니다:
void UAuraAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
}
}
이런 식으로 변경된 값이 무엇인지 보고 추가 작업을 할 수 있는 것이다.
또 다른 작업을 해보자
void UAuraAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
// Source = 이펙트를 일으킨 유발자, Target = 이펙트를 받는 대상 (이 Attribute Set의 주인)
const FGameplayEffectContextHandle EffectContextHandle = Data.EffectSpec.GetContext();
const UAbilitySystemComponent* SourceASC = EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent();
if (IsValid(SourceASC) && SourceASC->AbilityActorInfo.IsValid() && SourceASC->AbilityActorInfo->AvatarActor.IsValid())
{
AActor* SourceAvatarActor = SourceASC->AbilityActorInfo->AvatarActor.Get();
const AController* SourceController = SourceASC->AbilityActorInfo->PlayerController.Get();
if (SourceController == nullptr && SourceAvatarActor != nullptr)
{
if (APawn* Pawn = Cast<APawn>(SourceAvatarActor))
{
SourceController = Pawn->GetController();
}
}
if (SourceController)
{
ACharacter* SourceCharacter = Cast<ACharacter>(SourceController->GetPawn());
}
}
if (Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
{
AActor* TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
AController* TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
ACharacter* TargetCharacter = Cast<ACharacter>(TargetActor);
const UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);
}
}
위의 구문은 두 단계로 나누어져 있는데 첫번째 단계에서는 소스의 컨트롤러와 아바타액터, 캐릭터 클래스 등을 구하는 것이고,
두번째 단계에서는 타겟의 액터와 컨트롤러, ASC 등을 구하는 중이다.
그리고 이러한 값들을 저장하면 나중에 다양하게 쓰일 수 있다. 단순히 변수로 저장해도 되지만 쉽게 모든 값을 다룰 수 있게 구조체로 만들어서 저장하려고 한다.
2. 정보들 구조체로 저장하기
어트리뷰트 세트의 헤더파일로 가서 구조체를 정의하자.
USTRUCT()
struct FEffectProperties
{
GENERATED_BODY()
FEffectProperties() {}
FGameplayEffectContextHandle EffectContextHandle;
UPROPERTY()
UAbilitySystemComponent* SourceASC = nullptr;
UPROPERTY()
AActor* SourceAvatarActor = nullptr;
UPROPERTY()
AController* SourceController = nullptr;
UPROPERTY()
ACharacter* SourceCharacter = nullptr;
UPROPERTY()
UAbilitySystemComponent* TargetASC = nullptr;
UPROPERTY()
AActor* TargetAvatarActor = nullptr;
UPROPERTY()
AController* TargetController = nullptr;
UPROPERTY()
ACharacter* TargetCharacter = nullptr;
};
이제 이 구조체를 채우는 함수를 만들면 된다.
void SetEffectProperties(const FGameplayEffectModCallbackData& Data, FEffectProperties& Props);
해당 함수 내부에는 위에서 작성했던 로직을 그래로 붙여넣고 지역변수로 저장한 값을 구조체에 할당해주기만 하면 된다.
void UAuraAttributeSet::SetEffectProperties(const FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const
{
// Source = 이펙트를 일으킨 유발자, Target = 이펙트를 받는 대상 (이 Attribute Set의 주인)
Props.EffectContextHandle = Data.EffectSpec.GetContext();
Props.SourceASC = Props.EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent();
if (IsValid(Props.SourceASC) && Props.SourceASC->AbilityActorInfo.IsValid() && Props.SourceASC->AbilityActorInfo->AvatarActor.IsValid())
{
Props.SourceAvatarActor = Props.SourceASC->AbilityActorInfo->AvatarActor.Get();
Props.SourceController = Props.SourceASC->AbilityActorInfo->PlayerController.Get();
if (Props.SourceController == nullptr && Props.SourceAvatarActor != nullptr)
{
if (APawn* Pawn = Cast<APawn>(Props.SourceAvatarActor))
{
Props.SourceController = Pawn->GetController();
}
}
if (Props.SourceController)
{
Props.SourceCharacter = Cast<ACharacter>(Props.SourceController->GetPawn());
}
}
if (Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
{
Props.TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
Props.TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
Props.TargetCharacter = Cast<ACharacter>(Props.TargetAvatarActor);
Props.TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Props.TargetAvatarActor);
}
}
이제 다시 아래 함수를 재정의하면 된다.
void UAuraAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
FEffectProperties Props;
SetEffectProperties(Data, Props);
}
이렇게 해서 정보에 손 쉽게 접근이 가능해졌다. 이는 추후 전투 기능을 만들때 유용하게 쓰일 것이라고 한다.
'게임프로그래밍 > 실습2' 카테고리의 다른 글
[실습2] 27. 태그 브로드 캐스팅 하기 - 1 (0) | 2024.11.30 |
---|---|
[실습2] 26. 게임 플레이 이펙트에 게임플레이 태그 적용하고 태그 출력하기 (0) | 2024.11.30 |
[실습2] 24. PreAttributeChange 함수로 클램핑 적용하기 (0) | 2024.11.30 |
[실습2] 23. C++에서 인피니트 게임플레이 이펙트 제거하기 (0) | 2024.11.30 |
[실습2] 22. 인스턴트 게임플레이 이펙트 (0) | 2024.11.29 |