Gameplay Attribute
- 캐릭터의 상태를 나타내는 값으로 예를 들어 체력, 마나, 스태미나같은 스탯이 있습니다.
- 속성은 능력이나 효과의 영향을 받으며 게임 내 캐릭터의 능력 발동과 직접적으로 연결됩니다.
- 지금은 캐릭터 클래스에서 Hp 같은 스탯을 관리하지만 GameplayAttribute를 이용해 관리합니다.
AttributeSet을 상속받은 클래스 생성
- 몬스터와 캐릭터들에만 존재하는 스탯이 있는 경우 해당 클래스를 상속받아 따로 관리할 수 있다.
- 만든 클래스를 상속받아 몬스터와 플레이어의 AttributeSet 생성
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
- 매크로 함수를 하나 만드는데 GameplayAttribute의 Value를 get, set, init 할 수 있도록 한다
public:
UMyAttributeSet();
public:
ATTRIBUTE_ACCESSORS(ThisClass, Health);
ATTRIBUTE_ACCESSORS(ThisClass, MaxHealth);
ATTRIBUTE_ACCESSORS(ThisClass, Mana);
ATTRIBUTE_ACCESSORS(ThisClass, MaxMana);
ATTRIBUTE_ACCESSORS(ThisClass, BaseDamage);
ATTRIBUTE_ACCESSORS(ThisClass, BaseDefense);
private:
UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
FGameplayAttributeData Health;
UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
FGameplayAttributeData MaxHealth;
UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
FGameplayAttributeData Mana;
UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
FGameplayAttributeData MaxMana;
UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
FGameplayAttributeData BaseDamage;
UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
FGameplayAttributeData BaseDefense;
UMyAttributeSet::UMyAttributeSet()
{
InitHealth(100.0f);
InitMaxHealth(100.0f);
}
- FGameplayAttributeData는 Base와 Current 2가지의 값을 float으로 가지고 있다.
- ATTRIBUTE_ACCESSORS 매크로를 이용해 get, set, init에 대한 함수를 모두 만든 것과 같다.
- InitHealth와 같은 함수를 사용할 수 있는 이유가 매크로를 통해 만들어주었기 때문에 가능하다.
캐릭터에 AttributeSet 추가
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<class UMyAttributeSet> AttributeSet;
- 플레이어의 경우 PlayerState에서 생성해 AbilitySystemComponent와 생명주기를 같이한다.
public:
UMyAbilitySystemComponent* GetMyAbilitySystemComponent() const;
UMyPlayerSet* GetMyPlayerSet() const;
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<class UMyPlayerSet> PlayerSet;
AMyPlayerState::AMyPlayerState(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
AbilitySystemComponent = CreateDefaultSubobject<UMyAbilitySystemComponent>("AbilitySystemComponent");
PlayerSet = CreateDefaultSubobject<UMyPlayerSet>("PlayerSet");
}
UMyAbilitySystemComponent* AMyPlayerState::GetMyAbilitySystemComponent() const
{
return AbilitySystemComponent;
}
UMyPlayerSet* AMyPlayerState::GetMyPlayerSet() const
{
return PlayerSet;
}
플레이어에서 AttributeSet 초기화
void AMyPlayer::InitAbilitySystem()
{
Super::InitAbilitySystem();
if(AMyPlayerState* PS = GetPlayerState<AMyPlayerState>())
{
AbilitySystemComponent = Cast<UMyAbilitySystemComponent>(PS->GetAbilitySystemComponent());
AbilitySystemComponent->InitAbilityActorInfo(PS, this);
AttributeSet = PS->GetMyPlayerSet();
}
}
캐릭터에서 데미지를 AttributeSet을 이용하여 변경
void AMyCharacter::OnDamaged(int32 Damage, TObjectPtr<AMyCharacter> Attacker)
{
float Hp = AttributeSet->GetHealth();
float MaxHp = AttributeSet->GetMaxHealth();
Hp = FMath::Clamp(Hp - Damage, 0, MaxHp);
AttributeSet->SetHealth(Hp);
if (Hp == 0)
{
OnDead(Attacker);
}
RefreshHpBarRatio();
}
void AMyCharacter::RefreshHpBarRatio()
{
if (HpBarComponent && AttributeSet)
{
float Hp = AttributeSet->GetHealth();
float MaxHp = AttributeSet->GetMaxHealth();
float Ratio = static_cast<float>(Hp) / MaxHp;
UMyHpBarWidget* HpBar = Cast<UMyHpBarWidget>(HpBarComponent->GetUserWidgetObject());
HpBar->SetHpRatio(Ratio);
}
}
Gameplay Effect
- 능력이 발동될 때 일시적 또는 지속적인 변화를 캐릭터에게 부여하는 요소
- 예를 들어 공격력 증가, 체력 회복, 상태 이상 등
- 효과는 속성에 직접적인 변화를 주어 특정 시간 동안 유지되거나 조건에 따라 종료
Gameplay Effect 블루프린트 클래스를 만들어보자

- 수치 값들을 가지고 있는 하나의 데이터 파일이라고 볼 수도 있다.
- Duration Policy
- Instant: 단발성으로 한 번만 실행되고 끝남
- Infinite: 패시브처럼 계속 적용되는 것들
- Has Duration: 특정 기간만큼 유효함
- Period: 특정 기간 마다 효과를 적용할 수 있음
- 예를 들어 10초 동안 1초마다 데미지를 입는 경우
- Duration은 10 Period는 1

- Modifiers의 다양한 옵션을 통해 효과를 설정할 수 있다