AttributeSet.h에서 제공하는 Getter, Setter, Initter 매크로를 통해 별도의 Getter, Setter, Initter 함수를 구현할 필요 없이 손쉽게 사용할 수 있음.
또한, 해당 매크로들을 매 번 입력할 필요 없이 묶어서 쓸 수 있게 해주는 매크로도 제공.
This defines a set of helper functions for accessing and initializing attributes, to avoid having to manually write these functions.
It would creates the following functions, for attribute Health
static FGameplayAttribute UMyHealthSet::GetHealthAttribute();
FORCEINLINE float UMyHealthSet::GetHealth() const;
FORCEINLINE void UMyHealthSet::SetHealth(float NewVal);
FORCEINLINE void UMyHealthSet::InitHealth(float NewVal);
To use this in your game you can define something like this, and then add game-specific functions as necessary:
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
ATTRIBUTE_ACCESSORS(UMyHealthSet, Health)
// 위 내용은 Attribute.h에 적힌 주석으로,
// 예를 들어 GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName)를 통해
// static FGameplayAttribute UMyHealthSet::GetHealthAttribute(); 가 즉시 사용할 수 있게 됨.
// 매크로를 통해 실제 구현되는 함수들은 아래와 같음.
#define GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
static FGameplayAttribute Get##PropertyName##Attribute() \
{ \
static FProperty* Prop = FindFieldChecked<FProperty>(ClassName::StaticClass(), GET_MEMBER_NAME_CHECKED(ClassName, PropertyName)); \
return Prop; \
}
#define GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
FORCEINLINE float Get##PropertyName() const \
{ \
return PropertyName.GetCurrentValue(); \
}
#define GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
FORCEINLINE void Set##PropertyName(float NewVal) \
{ \
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent(); \
if (ensure(AbilityComp)) \
{ \
AbilityComp->SetNumericAttributeBase(Get##PropertyName##Attribute(), NewVal); \
}; \
}
#define GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName) \
FORCEINLINE void Init##PropertyName(float NewVal) \
{ \
PropertyName.SetBaseValue(NewVal); \
PropertyName.SetCurrentValue(NewVal); \
}
// 위의 매크로들은 단순히 AttributeSet 상속 클래스에
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
// 위 매크로를 정의하는 것만으로도 사용할 수 있음.
// AuraAttributeSet.h
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Vital Attribute")
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Health);
// AuraAttributeSet.cpp
UAuraAttributeSet::UAuraAttributeSet()
{
InitHealth(100.f);
}
다만, Attribute들은 GameplayEffect를 통해 변경하는 것이 일반적이므로,
이러한 접근자 함수를 통해 Attribute를 변경하는 일은 가급적 피하는 것이 좋음.