25.11.14 내일배움캠프 [Unreal_5기] TIL - GAS 기초 (2)

mingu Lee·2025년 11월 14일

1. 간단 요약


  • 프로그래머스 문제 풀이 진행
  • GameplayAttributeData와 AttributeSet을 배우고, AttributeSet과 HUD를 Bind하여 AttributeData 값에 따라 HUD도 연동되는 실습을 진행
  • Gameplay Effect를 사용하여 Ability와 AttributeSet을 연동하여 처리하는 실습을 진행
  • Meta Attribute의 개념을 배우고, 이를 AttributeSet에서 구현하는 방법을 학습
  • NPC의 반격 기능을 구현하는 실습을 진행

2. 세부 과정


  1. 프로그래머스 문제 풀이
  2. AttributeSet과 HUD 연동
  3. Ability와 AttributeSet 연동
  4. Meta Attribute와 NPC의 반격 기능

2-1. 프로그래머스 문제 풀이


1. 디스크 컨트롤러 (Lv.3)

https://school.programmers.co.kr/learn/courses/30/lessons/42627

  • 현재 작업 중 들어온 작업이라면 우선순위 큐에 Push
  • 우선순위 큐는 (걸리는 시간, 시작 시간, Index) 순으로 정렬
  • 현재 작업이 끝났다면 우선순위 큐의 top 작업을 진행

2-2. AttributeSet과 HUD 연동


유튜브 게임플레이 어빌리티 시스템(GAS)으로 RPG 시스템 만들기 5강의 목표.

AttributeSet은 다수의 GameplayAbilityData를 묶어 관리하는 언리얼 오브젝트.

플레이어의 Health를 관리하기 위해 AttributeSet 클래스를 생성.

UCLASS()
class ARENABATTLEGAS_API UABCharacterAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
	
public:
	UABCharacterAttributeSet();

	ATTRIBUTE_ACCESSORS_BASIC(ThisClass, MaxHealth);
	ATTRIBUTE_ACCESSORS_BASIC(ThisClass, Health);

	virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
	virtual void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override;

protected:
	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	FGameplayAttributeData MaxHealth;

	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	FGameplayAttributeData Health;
};

하나의 스탯마다 Max 값, 실제 값 FGameplayAttributeData 2개를 선언하는 것을 권장.

각 스탯마다 Getter, Setter, Initialize 함수가 필요하면 필요한 함수 x 2개를 선언해야 하는데, Unreal에서는 이를 매크로로 제공해줌.

ATTRIBUTE_ACCESSORS_BASIC(Class, FGameplayAttributeData) 형식으로 선언.

위 매크로를 살펴보면 다음과 같은 함수를 제공해줌.

제공된 함수를 사용하여 PreAttributeChange, PostAttributeChange 함수에서 무결성 검사 및 UI 연동 가능.

void UABCharacterAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
	if (Attribute == GetMaxHealthAttribute())
	{
		NewValue = FMath::Max(1.0f, NewValue);
	}
	else if (Attribute == GetHealthAttribute())
	{
		NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth());
	}
}

위와 같이 Attribute 값이 변경되기 전에 호출되는 PreAttributeChange에서 무결성을 검사.

CharacterAttributeSet에 AttributeData가 변경될 때 이를 알리기 위한 Delegate를 선언.

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAttributeDataChanged, float, OldValue, float, NewValue);

UPROPERTY(BlueprintAssignable, Category = "Attribute")
mutable FAttributeDataChanged OnMaxHealthChanged;

UPROPERTY(BlueprintAssignable, Category = "Attribute")
mutable FAttributeDataChanged OnHealthChanged;

PostAttributeChange 함수에서 Delegate를 통해 Broadcast.

void UABCharacterAttributeSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
	if (Attribute == GetMaxHealthAttribute())
	{
		OnMaxHealthChanged.Broadcast(OldValue, NewValue);
	}
	else if (Attribute == GetHealthAttribute())
	{
		OnHealthChanged.Broadcast(OldValue, NewValue);
	}
}

플레이어는 PostInitializeComponents 함수에서 AttributeSet을 HUD에 전달하여 각 Delegate를 Bind.

간단한 테스트를 위해 다음과 같이 스탯을 설정.

ASC->SetNumericAttributeBase(CharacterAttributeSet->GetMaxHealthAttribute(), 0.1f);
ASC->SetNumericAttributeBase(CharacterAttributeSet->GetHealthAttribute(), 200.0f);

위와 같이 작성했을 때, AttributeSet의 PreAttributeChange 함수에 의해 무결성 처리가 자동으로 됨.

MaxHealth를 200.0f 값으로 설정하면 제대로 되는 것을 확인할 수 있음.

강의 요약.

2-3. Ability와 AttributeSet 연동


유튜브 게임플레이 어빌리티 시스템(GAS)으로 RPG 시스템 만들기 6강의 목표.

Ability가 발동했을 때 Gameplay Effect를 사용하여 Attribute의 값의 변화를 줄 수 있음.

Gameplay Effect는 블루프린트 에디터에서 설정하는 것을 권장함.

플레이어 공격에 NPC가 피격됐을 때, NPC의 Health를 감소시키기 위해 Gameplay Effect를 생성함.

GE를 생성하면 에디터에서 다음과 같은 설정들을 볼 수 있음.

데미지는 즉시 감소시켜야 하기에 Duration Policy는 Instant로 설정.

Attribute의 수치 변화를 설정하는 Section은 Modifier.

Modifier를 추가하고 Attribute를 눌러보면 AttributeSet에서 내가 설정한 변수들이 보임.

Health를 감소시켜야 하기 때문에 Health를 선택하고 값을 설정.

이후 HitCheck Gameplay Ability에서 ApplyGameplayEffectToTarget 노드를 사용하여 Target과 GE를 설정.

Attribute의 특정 값의 BaseValue가 Gameplay Effect에 의해 변경되었다면, PreGameplayEffectExcutePostGameplayEffectExcute가 호출됨.

Health가 0이하로 되었을 때 사망 처리를 하기 위해 PostGameplayEffectExcute에서 로직 구현.

void UABCharacterAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
	if (GetHealth() <= 0.0f)
	{
		OnOutOfHealth.Broadcast(Data.EffectSpec.GetEffectContext().GetInstigator());
	}
}

OnOutOfHealth라는 Delegate를 BP_NPC에서 Bind하여 사망 처리 로직을 설정해줌.

강의 요약.

2-4. Meta Attribute와 NPC의 반격 기능


유튜브 게임플레이 어빌리티 시스템(GAS)으로 RPG 시스템 만들기 7강의 목표.

Meta Attribute는 다양한 상황에 유연하게 대응할 수 있도록 정의된 임시 Attribute.

기존 CharacterAttributeSet에 Damage라는 Data를 추가하고, PostGameplayEffectExecute에서 Damage에 관한 로직을 설정.

void UABCharacterAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
	if (Data.EvaluatedData.Attribute == GetDamageAttribute())
	{
		float AppliedDamage = 0.0f;
		float RemainingDamage = GetDamage();

		float OldHealth = GetHealth();
		float NewHealth = OldHealth - RemainingDamage;
		SetHealth(NewHealth);

		AppliedDamage = OldHealth - NewHealth;
		OnDamageApplied.Broadcast(Data.EffectSpec.GetEffectContext().GetInstigator(), AppliedDamage);
		SetDamage(0.0f);
	}

	if (GetHealth() <= 0.0f)
	{
		OnOutOfHealth.Broadcast(Data.EffectSpec.GetEffectContext().GetInstigator());
	}
}

이후 Attack에 관련된 값을 갖는 CombatAttribute를 생성.

UCLASS()
class ARENABATTLEGAS_API UABCombatAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
	
public:
	UABCombatAttributeSet();

protected:
	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	FGameplayAttributeData AttackRate;

	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	FGameplayAttributeData AttackRange;

	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	FGameplayAttributeData AttackRadius;
};

AttackDamage라는 GameplayEffect를 만들고, CombatAttributeSet의 AttackRate 값으로 CharacterAttributeSet의 Damage를 Override.

NPC도 Damage를 입었을 때 Attack Ability를 발동하도록 BP 수정.

이때 NPC의 공격이 플레이어에게 적중하지 않는 문제가 있는데, 이는 NPC가 Client가 아니기 때문에 TargetData가 생성되지 않음.

이를 해결하려면 TargetActor의 생성자에 ShouldProduceTargetDataOnServer = true; 코드를 추가.

서버가 직접 TargetData를 생성하도록 하여 NPC의 공격이 정상적으로 작동하게 수저.

다음으로 AttackUp이라는 Gameplay Effect를 생성하고, NPC는 게임 시작 시 AttackRate가 증가된 상태가 되게끔 해줌.

플레이어한테도 Death Ability를 부여하고, OutOfHealth Delegate에 Bind하여 Ability를 발동하도록 BP 구현.

사망 후 5초 뒤에 Level이 재시작되도록 함.

강의 요약.

3. 문제 발생 및 해결 방안


문제 사항 없음.

profile
Github: https://github.com/dlalsrn

0개의 댓글