0. 개요

기존에 제작했던 AuraEffectActor 클래스는 일종의 물약으로, 접촉하면 체력과 마나를 수정하는 클래스였다.

기존에는 강제로 속성 세트의 const를 제거하여 값을 변동하는 방법을 사용했으나, 이제부터는 게임플레이 이펙트를 통해 값을 변경하는 식으로 리펙토링을 진행한다.

기존에 Sphere와 Mesh를 생성자에서 지정하던 것을 제거하고, 이 클래스를 상속받은 블루프린트 클래스에서 생성하도록 한다.

 

 

1. 코드

#include "Actor/AuraEffectActor.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "AuraEffectActor.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemInterface.h"


AAuraEffectActor::AAuraEffectActor()
{
	PrimaryActorTick.bCanEverTick = false;

	// 메시와 형태는 블루프린트에서 지정 - 기능은 C++에서 지정
	SetRootComponent(CreateDefaultSubobject<USceneComponent>("SceneRoot"));
}

void AAuraEffectActor::BeginPlay()
{
	Super::BeginPlay();
}

void AAuraEffectActor::ApplyEffectToTarget(AActor *Target, TSubclassOf<UGameplayEffect> GameplayEffectClass)
{
	// 타겟의 어빌리티 시스템 인터페이스 가져옴
	UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target);
	if (TargetASC == nullptr)
		return;
	
	check(GameplayEffectClass);
	// Gameplay Effect Context 생성
	FGameplayEffectContextHandle EffectContextHandle = TargetASC->MakeEffectContext();

	// 이펙트 발생자에 대한 정보 추가
	EffectContextHandle.AddSourceObject(this);

	// Gameplay Effect Spec 생성
	const FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass, 1.f, EffectContextHandle);
	
	// Gameplay Effect Spec을 본인에게 적용
	TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());

}

(1) 어빌리티 시스템 컴포넌트에 접근하기

아래의 두 방법 중 하나를 사용한다. 두 방법은 동일하게 작동한다.

 

(1-1) 캐스팅

효과가 적용될 대상의 어빌리티 시스템 컴포넌트에 접근하기 위해 대상을 어빌리티 시스템 인터페이스로 캐스팅해서 어빌리티 시스템 컴포넌트를 가져올 수 있다.

	// 타겟의 어빌리티 시스템 인터페이스 가져옴
	IAbilitySystemInterface* ASCInterface = Cast<IAbilitySystemInterface>(Target);
	if (ASCInterface)
	{
		ASCInterface->GetAbilitySystemComponent();
   	 }

 

 

(1-2) 어빌리티 시스템 블루프린트 라이브러리 사용

또는 어빌리티 시스템 라이브러리를 이용하여 바로 꺼내올 수 있다.

UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target);

이 방법은 위에서 수행한 작업을 똑같이 수행한다.

(액터를 가져와 인터페이스로 캐스팅해서 어빌리티 시스템 컴포넌트를 가져온다)

 

 

(2) ASC를 이용해 게임플레이 이펙트 적용하기

ASC의 멤버 함수에 접근하면 다양한 함수가 나타나는 것을 볼 수 있다.

본인에게 효과를 적용하거나, 대상에 적용할 수 있다.

이 함수를 이용하려면 게임플레이 이펙트 스펙(Gameplay Effect Spec)이 필요하다.

 

 

(3) ASC를 이용해 게임플레이 이펙트 스펙 생성

게임플레이 이펙트 스펙을 생성하기 위해서 게임플레이 이펙트 컨텍스트가 필요하다.

 

 

(4) ASC를 이용해 게임플레이 이펙트 컨텍스트 생성

 

- 게임플레이 이펙트 컨텍스트(Gameplay Effect Context)

효과를 받는 사람 / 효과 발생시킨 사람 / 어떤 효과인지에 대한 정보가 담겨있는 구조체이다.

데미지가 있거나 없는 모든 효과에 대한 구조체이다.

 

게임플레이 이펙트 컨텍스트 핸들은 위의 구조체를 포인터로 저장한다. 실제 정보는 Data로 들고 있다.

	// Gameplay Effect Context 생성
	FGameplayEffectContextHandle EffectContextHandle = TargetASC->MakeEffectContext();

	// 이펙트 발생자에 대한 정보 추가
	EffectContextHandle.AddSourceObject(this);

이펙트 컨텍스트 핸들에 이펙트 발생자에 대한 정보를 추가한다.

 

 

(5) 게임플레이 스펙 생성 및 적용

	// Gameplay Effect Spec 생성
	FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass, 1.f, EffectContextHandle);
	
	// Gameplay Effect Spec을 본인에게 적용
	TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());

모든 핸들은 내부에 Shared Ptr로 Data를 가지고 있다.

따라서 해당 Data의 원시 포인터에 접근하려면 Get 함수를 사용한다.

원시 포인터를 역참조하여 주소 값을 가져올 수 있다.