Udemy Unreal - Gameplay Ability System - Top Down RPG (Section 3)

๊น€์ข…๋ฏผยท2025๋…„ 3์›” 21์ผ

Udemy Unreal - GAS

๋ชฉ๋ก ๋ณด๊ธฐ
3/7

๐Ÿ“– ์œ ๋ฐ๋ฏธ GAS ๊ฐ•์˜ ์ค‘ ๊ธฐ๋กํ•ด๋‘๊ณ  ์‹ถ์€ ๋‚ด์šฉ์„ ์ ์–ด๋‘” ํฌ์ŠคํŠธ

Section 3 : GAS์— AttributeSet ์ถ”๊ฐ€ํ•˜๊ธฐ


AttributeSet

ASC(AbilitySystemComponent)์— ์—ฌ๋Ÿฌ AttributeSet ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  • ํ•˜๋‚˜์˜ Attribute Set ํด๋ž˜์Šค ์•ˆ์— ์—ฌ๋Ÿฌ Attribute ๋ชฉ๋ก์„ ๊ฐ–๋„๋กํ•˜๊ฑฐ๋‚˜
  • ํ•˜๋‚˜์˜ ๋ชฉ๋ก์„ ๊ฐ€์ง„ ์—ฌ๋Ÿฌ Attribute Set ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (์ด ๊ฒฝ์šฐ ๋ชจํ˜ธ์„ฑ ๋ฌธ์ œ๋•Œ๋ฌธ์— AttributeSet ํด๋ž˜์Šค๋Š” ๋‹ค๋ฅด๊ฒŒ ์จ์•ผํ•จ)

Prediction

Attribute ๊ฐ’์„ ์กฐ์ •ํ•˜๋Š” ๋ฐฉ์‹์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์ง€๋งŒ ์˜ˆ์ œ์—์„œ๋Š” ๊ฒŒ์ž„ํ”Œ๋ ˆ์ด ์ดํŽ™ํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ์–ธ๋ฆฌ์–ผ ์—”์ง„์—์„œ ์ง€์›ํ•˜๋Š” ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฉ์‹์ธ ๋กœ์ปฌ ์˜ˆ์ธก ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ๋•Œ๋ฌธ

๋กœ์ปฌ ์˜ˆ์ธก ๋ฐฉ์‹(Local Predicted)์ด๋ž€

๋ฐ˜์‘์„ฑ๊ณผ ์ •ํ™•์„ฑ ์‚ฌ์ด์— ๊ท ํ˜•์ด ์ž˜ ์žกํžŒ ์˜ต์…˜์ž…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ช…๋ น์„ ๋‚ด๋ฆฌ๋ฉด ๋กœ์ปฌ ํด๋ผ์ด์–ธํŠธ์—์„œ ์–ด๋นŒ๋ฆฌํ‹ฐ๊ฐ€ ์ฆ‰์‹œ ์‹คํ–‰๋˜์ง€๋งŒ, ์–ด๋นŒ๋ฆฌํ‹ฐ์˜ ์‹ค์ œ ์˜ํ–ฅ์ด ์–ด๋• ๋Š”์ง€์— ๋Œ€ํ•œ ์ตœ์ข… ๊ฒฐ์ •์€ ์„œ๋ฒ„๊ฐ€ ๋‚ด๋ฆฌ๊ณ  ํด๋ผ์ด์–ธํŠธ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์— ์–ด๋นŒ๋ฆฌํ‹ฐ ์‹คํ–‰ ๊ถŒํ•œ์„ ์š”์ฒญํ•˜์ง€๋งŒ, ํด๋ผ์ด์–ธํŠธ ๊ด€์ ์˜ ๊ฒฐ๊ณผ๋ฅผ ์„œ๋ฒ„๊ฐ€ ๋™์˜ํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๊ณ  ๋กœ์ปฌ์—์„œ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ๋กœ์ปฌ์—์„œ ์–ด๋นŒ๋ฆฌํ‹ฐ์˜ ๋น„ํ—ค์ด๋น„์–ด๋ฅผ ์˜ˆ์ธกํ•˜๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ์˜ ์˜ˆ์ธก์ด ์„œ๋ฒ„์™€ ๋ชจ์ˆœ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ง€์—ฐ ์—†์ด ์™„์ „ํžˆ ๋งค๋„๋Ÿฝ๊ฒŒ ๋А๊ปด์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ถœ์ฒ˜ : ์–ธ๋ฆฌ์–ผ ๊ณต์‹ ๋ฌธ์„œ

FGameplayAttributeData


Attribute๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ตฌ์กฐ์ฒด๋กœ BaseValue์™€ CurrentValue๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค.

  • BaseValue ๋Š” MaxValue๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ HealthAttribute๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•  ๋•Œ Base๋ฅผ MaxHealth์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ  MaxHealthAttribute๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉ
  • ๊ฐ Value๋Š” floatํ˜•

Attribute ์ถ”๊ฐ€ํ•˜๊ธฐ

ํฌ๊ฒŒ ์„ธ๊ฐ€์ง€ ๊ณตํ†ต ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค.
1. ReplicatedUsing ํด๋ž˜์Šค ์ง€์ •์ž์™€ RepNotify ์ถ”๊ฐ€ํ•˜๊ธฐ
2. GetLifetimeReplicatedProps์— ๋ณ€์ˆ˜ ๋“ฑ๋กํ•˜๊ธฐ
3. GAMEPLAYATTRIBUTE_REPNOTIFY๋กœ ASC์™€ ์—ฐ๋™ํ•˜๊ธฐ

1. ReplicatedUsing ํด๋ž˜์Šค ์ง€์ •์ž์™€ RepNotify ์ถ”๊ฐ€ํ•˜๊ธฐ

UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_Health,Category="Vital Attributes")
	FGameplayAttributeData Health;
  • ReplicatedUsing ํด๋ž˜์Šค ์ง€์ •์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  RepNotify ํ•จ์ˆ˜๋ช…์„ ๋‹ฌ์•„์ค€๋‹ค.
UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldHealth) const;
  • ๋™์ผํ•œ ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.
  • ์ธ์ž์— ์ด์ „๊ฐ’์„ ์ฐธ์กฐ๋กœ ๋ฐ›์•„์˜ค๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. (ํ•„์š”์—†์œผ๋ฉด ๋นผ๋„ ๋จ)

2. GetLifetimeReplicatedProps์— ๋ณ€์ˆ˜ ๋“ฑ๋กํ•˜๊ธฐ

GetLifetimeReplicatedProps ํ•จ์ˆ˜๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•œ ๋’ค
DOREPLIFETIME_CONDITION_NOTIFY ๋งคํฌ๋กœ๋ฅผ ํ†ตํ•ด Attribute๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.

void UAuraAttributeSet::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet,Health,COND_None,REPNOTIFY_Always);
}

DOREPLIFETIME_CONDITION_NOTIFY(ํด๋ž˜์Šค, ๋ฉค๋ฒ„, ์กฐ๊ฑด, ๋…ธํ‹ฐํŒŒ์ด ์„ค์ •)

  • COND_None : ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜๋˜๋Š” ๋ฐฉ์‹์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ (None์€ ํ•ญ์ƒ ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜๋˜๋„๋ก ํ•จ)
  • ๋งˆ์ง€๋ง‰ ์ธ์ž์ธ REPNOTIFY_Always๋Š” ํ•ญ์ƒ ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜๋˜๋„๋ก ์„ค์ •ํ•œ ๊ฒƒ.
    (๊ธฐ๋ณธ๊ฐ’์€ REPNOTIFY_OnChanged๋กœ ๋กœ์ปฌ ๊ฐ’๊ณผ ๋‹ค๋ฅผ ๋•Œ๋งŒ ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜)

3. GAMEPLAYATTRIBUTE_REPNOTIFY๋กœ ASC์™€ ์—ฐ๋™ํ•˜๊ธฐ


void UAuraAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Health,OldHealth);
}

RepNotify ํ•จ์ˆ˜์—์„œ ๋ฆฌํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋  ๋•Œ ASC์—๋„ ์ „๋‹ฌ๋˜๋„๋ก ์‚ฌ์šฉํ•˜๋Š” ํ—ฌํผ ๋งคํฌ๋กœ์ด๋‹ค.

"This is a helper macro that can be used in RepNotify functions to handle attributes that will be predictively modified by clients."


Attribute Accessors

Attribute๋งˆ๋‹ค ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ผ์ด ๋งŽ์€ Getter, Setter, Init ๋“ฑ์˜ ํ•จ์ˆ˜๋ฅผ ์ผ์ผ์ด ๋งŒ๋“ค์ง€ ์•Š๋„๋ก ์ ‘๊ทผ์ž ์ƒ์„ฑ ๋งคํฌ๋กœ๋ฅผ ์ง€์›ํ•œ๋‹ค.

์‚ฌ์šฉ๋ฒ•

attributeset.h์„ ์ฐพ์•„๋ณด๋ฉด ATTRIBUTE_ACCESSORS๊ฐ€ ์ •์˜๋œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค.
ํ•ด๋‹น ๋งคํฌ๋กœ๋ฅผ ์ปค์Šคํ…€ ํด๋ž˜์Šค ํ—ค๋”์— ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

  • ์ฒ˜์Œ์— ์ฃผ์„์ฒ˜๋ฆฌ ๋˜์–ด์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ฃผ์„ ๋ถ€๋ถ„์ด๋ž‘ * ๋ถ€๋ถ„ ์ง€์›Œ์•ผ ํ•จ

์ถ”๊ฐ€ํ•  ๋ผ์ธ

#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

์‚ฌ์šฉ ์˜ˆ์‹œ

UPROPERTY(BlueprintReadOnly,ReplicatedUsing=OnRep_Health,Category="Vital Attributes")
	FGameplayAttributeData Health;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Health)

ATTRIBUTE_ACCESSORS(ํด๋ž˜์Šค,์†์„ฑ์ด๋ฆ„) ๋ฅผ ๋“ฑ๋กํ•˜๋ฉด ์ดํ›„

InitMaxHealth(100);
InitHealth(GetMaxHealth());

์ด๋Ÿฐ์‹์œผ๋กœ Get์†์„ฑ์ด๋ฆ„Attribute, Get์†์„ฑ์ด๋ฆ„, Set์†์„ฑ์ด๋ฆ„, Init์†์„ฑ์ด๋ฆ„ 4๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•จ์ˆ˜ ์›ํ˜•

#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); \
	}

๊ฐ ํ•จ์ˆ˜์˜ ๊ธฐ๋Šฅ

Get์†์„ฑ์ด๋ฆ„Attribute : FGameplayAttribute ๊ตฌ์กฐ์ฒด๋ฅผ ๋ฆฌํ„ด
Get์†์„ฑ์ด๋ฆ„ : CurrentValue๋ฅผ ๋ฆฌํ„ด
Set์†์„ฑ์ด๋ฆ„ : BaseValue๋ฅผ ์„ค์ •
Init์†์„ฑ์ด๋ฆ„ : BaseValue์™€ CurrentValue๋ฅผ ๋™์‹œ์— ์„ค์ •


showdebug abilitysystem

์ฝ˜์†” ๋ช…๋ น์–ด showdebug abilitysystem ์„ ์ž…๋ ฅํ•ด ์—”์ง„์—์„œ ๋””๋ฒ„๊น…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
(์Šคํฌ๋ฆฐ์ƒท ์ขŒ์ธก ์ค‘์•™์— ์†์„ฑ๊ณผ ๊ฐ’์ด ํ‘œ์‹œ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.)


์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด AttributeSet ์ ‘๊ทผํ•˜๊ธฐ

if (IAbilitySystemInterface* ASCInterface = Cast<IAbilitySystemInterface>(OtherActor))
{
		const UAuraAttributeSet* AuraAttributeSet = 
											Cast<UAuraAttributeSet>(ASCInterface->
											GetAbilitySystemComponent()->
											GetAttributeSet(UAuraAttributeSet::StaticClass()));
}
  1. OtherActor๊ฐ€ ASC ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์† ๋ฐ›์•˜๋‹ค๋ฉด ์บ์ŠคํŒ… ์„ฑ๊ณต
  2. ASC ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ํ•จ์ˆ˜์ธ GetAbilitySystemComponent()๋ฅผ ํ†ตํ•ด ์•กํ„ฐ์˜ ASC์— ์ ‘๊ทผ
  3. GetAttributeSet()์„ ํ†ตํ•ด ASC์— ๋“ฑ๋ก๋œ AttributeSet์— ์ ‘๊ทผํ•œ๋‹ค.
  • ASC๋Š” ์ดˆ๊ธฐํ™”๋  ๋•Œ ์ž๋™์œผ๋กœ OwnerActor์— ์กด์žฌํ•˜๋Š” AttributeSet์„ ์ฐพ์•„์„œ ์ปดํฌ๋„ŒํŠธ์— ๋“ฑ๋กํ•˜๋ฏ€๋กœ ๋”ฐ๋กœ ํ• ๋‹นํ•˜์ง€ ์•Š์•˜๋”๋ผ๋„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
  • GetAttributeSet()์˜ ์ธ์ž๋Š” TSubclassOf<UAttributeSet>์ด๋ฏ€๋กœ StaticClass()๋ฅผ ํ†ตํ•ด ๋„˜๊ฒจ์ค€๋‹ค.

์ปค๋ฐ‹

https://github.com/jongmin7759/Unreal_GAS/commit/799da6ebfcdfd0fc84d565ca6c900b71b9c132b7

profile
์ •๋ฆฌ์™€ ๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€