이번 포스트에서는 본격적인 GE를 도입하기 이전에 Attribute를 건드려보겠습니다.
Actor 클래스를 하나 추가하여 기존에 만든 Attribute Set의 Attribute 중 하나인 Health를 변경하겠습니다.
해당 클래스의 코드는 다음과 같습니다.
1) GE 설계 이전에 Attribute를 변경할 AAuraEffectActor
#pragma once
#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;
};
갖고 있는 함수는 총 4개입니다.
CDO의 기본 설정을 진행할 생성자와
SphereComponent에 Overlap 이벤트가 발생하면 호출될 BeginOverlap 함수,
Overlap 이벤트가 종료되면 호출될 EndOverlap 함수가 존재합니다.
그리고 SphereComponent와 Overlap 함수를 연결할 BeginPlay 함수입니다.
멤버 변수는 총 2개로서
충돌체의 역할을 수행할 SphereComponent와
Level에 배치된 Actor를 보여줄 StaticMeshComponent입니다.
이제 정의문을 보겠습니다.
#include "Actor/AuraEffectActor.h"
#include "Components/SphereComponent.h"
#include "AbilitySystemInterface.h"
#include "AbilitySystem/AuraAttributeSet.h"
AAuraEffectActor::AAuraEffectActor()
{
PrimaryActorTick.bCanEverTick = false;
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
SetRootComponent(Mesh);
Sphere = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere"));
Sphere->SetupAttachment(GetRootComponent());
}
void AAuraEffectActor::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
IAbilitySystemInterface* ASCInterface = Cast<IAbilitySystemInterface>(OtherActor);
if (ASCInterface)
{
const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(ASCInterface->GetAbilitySystemComponent()->GetAttributeSet(UAuraAttributeSet::StaticClass()));
// 일시적으로 const_cast를 사용하여 const를 삭제, 이때의 const_cast는 Native C++
// const_cast는 const 변수를 해제하므로 위험함 따라서 언제든지 수정될 수 있음을 염두해야 함
UAuraAttributeSet* MutableAttributeSet = const_cast<UAuraAttributeSet*>(AuraAttributeSet);
MutableAttributeSet->SetHealth(AuraAttributeSet->GetHealth() + 25.f);
Destroy();
}
}
void AAuraEffectActor::EndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
}
void AAuraEffectActor::BeginPlay()
{
Super::BeginPlay();
// SphereComponent에 Overlap 이벤트가 발생했을 경우 OnOverlap 함수를 호출하도록 설정
Sphere->OnComponentBeginOverlap.AddDynamic(this, &AAuraEffectActor::OnOverlap);
// SphereComponent에 Overlap 이벤트가 종료되었을 경우 EndOverlap 함수를 호출하도록 설정
Sphere->OnComponentEndOverlap.AddDynamic(this, &AAuraEffectActor::EndOverlap);
}
생성자에서 Tick 함수는 사용하지 않으므로 Tick은 꺼놓겠습니다.
그리고 Mesh와 SphereComponent를 생성하였습니다.
Overlap 이벤트가 발생하면 호출되는 BeginOverlap 함수에서는 다음의 로직을 수행합니다.
Overlap된 대상을 캐스트하여 ASC를 갖고 있는지 확인합니다.
이때 설정한 Attribute는 const로 선언되어 값을 변화시킬 수 없습니다.
따라서 Native C++ 캐스트인 const_cast를 사용하여 이를 해결하였습니다.
하지만 const인 데이터를 해제하는 것은 매우 위험하고 또 설계 방침에 어긋나므로
추후에 이 문제를 수정할 여지를 남기기 위해 주석을 달아놓았습니다.
Health를 변화시킨 후 Actor를 스스로 파괴합니다.
BeginPlay에서는 SphereComponent에 대해 Overlap 이벤트 시에 호출할 콜백 함수를 연결하였습니다.
언리얼 에디터로 넘어가보겠습니다.
언리얼 에디터에서는 AuraEffectActor를 상속받은 블루 프린트를 제작하였습니다.
이제 실제 실행 결과를 살펴보겠습니다.
의도한 대로 Attribute를 잘 변형시키고 스스로 파괴되는 것까지 확인하였습니다.