0. 개요

이전 포스트에서 속성(Attributes) 값을 Set, Init 등의 함수로 직접 변경하는 것보다 게임플레이 이펙트(Gameplay Effects)를 이용하여 변경하는 것이 유용하다는 것을 학습했다.

 

2-8. 속성 접근자(Attribute Accessors)

0. 개요아직 게임플레이 이펙트(Gameplay Effects)에 대해 배우지 않았으므로 해당 기능 없이 속성에 직접 접근하는 방법이 필요하다.Get 함수 또는 Set 함수를 만들지 않고 접근하는 방법을 사용한다.

crat.tistory.com

이번 포스트에서는 게임플레이 이펙트 대신에 어떤 액터에 충돌하면 값을 변화하는 방법을 사용해본다.

 

1. 코드

(1) AuraEffectActor.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "AuraEffectActor.generated.h"

class USphereComponent;

UCLASS()
class AURA_API AAuraEffectActor : public AActor
{
	GENERATED_BODY()
	
public:	
	AAuraEffectActor();

	UFUNCTION()
	virtual void OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	virtual void EndOverlap(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

protected:
	virtual void BeginPlay() override;

private:
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<USphereComponent> Sphere;

	UPROPERTY(VisibleAnywhere)
	TObjectPtr<UStaticMeshComponent> Mesh;

};

AuraEffectActor를 덮는 구체를 생성한다. 이후에 다른 액터가 이 구체에 닿으면 체력을 회복하게 만들 것이다.

 

(2) AuraEffectActor.cpp

#include "Actor/AuraEffectActor.h"
#include "Components/SphereComponent.h"

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

	Mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
	SetRootComponent(Mesh);

	Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");
	Sphere->SetupAttachment(GetRootComponent());
}

void AAuraEffectActor::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	// 액터의 어빌리티 시스템 인터페이스에 접근 -> 어빌리티 시스템 컴포넌트에 접근
	if (IAbilitySystemInterface* ASCInterface = Cast<IAbilitySystemInterface>(OtherActor))
	{
		// 제한적
		// 게임플레이 이펙트를 사용할 것

		// UAttributeSet 반환
		const UAuraAttributeSet* AuraAttributeSet = Cast<UAuraAttributeSet>(ASCInterface->GetAbilitySystemComponent()->GetAttributeSet(UAuraAttributeSet::StaticClass()));
		
		// Do not Try, 학습 목적, const 떼기
		UAuraAttributeSet* MutableAuraAttributeSet = const_cast<UAuraAttributeSet>(AuraAttributeSet);

		MutableAuraAttributeSet->SetHealth(AuraAttributeSet->GetHealth() + 25.f);

		// 충돌 후 액터 제거
		Destroy();
	}
}

void AAuraEffectActor::EndOverlap(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{

}

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

	// 오버랩에 콜백 함수 바인딩
	Sphere->OnComponentBeginOverlap.AddDynamic(this, &AAuraEffectActor::OnOverlap);
	Sphere->OnComponentEndOverlap.AddDynamic(this, &AAuraEffectActor::OnEndOverlap);
	
}

 

여기에서는 단순히 속성 세트를 캐스팅하여 가져오고 const를 제거하여 강제로 속성 값을 변경하도록 설정할 것이다.

 

강제적으로 값을 변화시키는 것은 일반적이지 않음에 유의한다.

 

이 구체 컴포넌트와의 충돌 시 상호작용을 구현하기 위해 OnOverlap 함수를 사용한다.

겹침의 끝을 판정하기 위해 EndOverlap 함수를 사용한다.

BeginPlay에서 콜백 함수를 바인딩한다.

 

(3) 단점

값을 변경하기 위해 const를 제거하는 것은 굉장히 위험한 작업이다.

또한, 변경할 값을 하드코딩 하는 것도 문제가 될 수 있다.

 

반면에 게임플레이 이펙트는 속성 세트의 유형을 신경쓸 필요가 없으며, 어떤 액터의 어떤 속성에든 적용 가능하므로 위의 방법을 이용하기 보다 게임플레이 이펙트를 사용하는 것이 적합하다.