역량강화 분반 - 챌린지 - GAS
1. GAS

| Ability | 캐릭터의 능력 (공격, 점프, 스킬) |
| Attribute | 캐릭터의 수치 (Health, Stamina, Mana) |
| Effect | 변화 (데미지, 힐, 버프, 디버프) |
| Tags | 상태 (Jumping, Stunned, Invincible) |
| Cue | 연출 (VFX, SFX) |
- GAS 아키텍처 전체

2. Attribute System
📌 Attribute = 캐릭터의 수치 데이터
- AttributeSet
📌 Attribute들의 집합
AttributeSet은 C++로 작성해야 합니다.
네트워크 복제 (UPROPERTY(Replicated)) Attribute 매크로 (ATTRIBUTE_ACCESSORS) 콜백 함수 (PreAttributeChange, PostGameplayEffectExecute)
이런 기능들이 C++에서만 가능합니다. Blueprint에서는 불가능!
- ASC (Ability System Component)

- 어빌리티 시스템 컴포넌트(ASC)는 게임플레이 어빌리티 시스템(GAS) 전체를 관리하는 핵심 컴포넌트
- 게임플레이 어빌리티와 관련 연산을 처리하는 중앙 처리 장치(CPU)와 같은 역할을 수행함
- 하나의 액터에는 하나의 ASC만 부착 가능
- 액터에 ASC가 부착되어 있어야 게임플레이 어빌리트를 활성화할 수 있음
- ASC가 부착된 액터 사이에서 GAS를 이용한 상호작용이 가능
ASC 초기화
// BeginPlay에서 초기화 (필수!)
ASC->InitAbilityActorInfo(this, this);
👉 InitAbilityActorInfo를 호출하지 않으면 ASC가 작동하지 않음!
- ASC 소유 방식 (2가지)
| 구분 | Character 직접 소유 | PlayerState 소유 |
| ASC 위치 | Character 클래스 내부 | PlayerState 클래스 내부 |
| Owner/Avatar | 둘 다 Character | Owner=PlayerState, Avatar=Character |
| 사용 케이스 | 싱글플레이어, 간단한 멀티 | 캐릭터 교체가 잦은 멀티플레이어 |
| 장점 | 구조 단순, 구현 쉬움 | 리스폰/빙의 시 데이터 유지 |
| 단점 | 캐릭터 죽으면 ASC도 소멸 | 구조 복잡, 초기화 타이밍 관리 필요 |
- Gameplay Debugger
showdebug abilitysystem
- 플레이 중 ` (백틱 키)
- 콘솔에 입력: showdebug abilitysystem
- 화면에 표시:
- Health 실시간 값
- MaxHealth
- ASC 상태
- …

// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "MyAttributeSet.generated.h"
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
UCLASS()
class SECOND_API UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UMyAttributeSet();
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override; // 멤버 변수 셋팅해주는 함수
UPROPERTY(BlueprintReadOnly, Category = "Attribute", ReplicatedUsing = OnRep_Health)
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)
UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldHealth);
UPROPERTY(BlueprintReadOnly, Category = "Attribute", ReplicatedUsing = OnRep_MaxHealth)
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth)
UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
// Stamina
UPROPERTY(BlueprintReadOnly, Category = "Attribute", ReplicatedUsing = OnRep_Stamina)
FGameplayAttributeData Stamina;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Stamina)
UFUNCTION()
void OnRep_Stamina(const FGameplayAttributeData& OldStamina);
UPROPERTY(BlueprintReadOnly, Category = "Attribute", ReplicatedUsing = OnRep_MaxStamina)
FGameplayAttributeData MaxStamina;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxStamina)
UFUNCTION()
void OnRep_MaxStamina(const FGameplayAttributeData& OldMaxStamina);
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue);
virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data);
};
#include "GAS/MyAttributeSet.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffect.h"
#include "GameplayEffectExtension.h"
UMyAttributeSet::UMyAttributeSet()
{
InitHealth(100.f);
InitMaxHealth(100.f);
InitStamina(10.f);
InitMaxStamina(10.f);
}
void UMyAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UMyAttributeSet, Health);
DOREPLIFETIME(UMyAttributeSet, MaxHealth);
DOREPLIFETIME(UMyAttributeSet, Stamina);
DOREPLIFETIME(UMyAttributeSet, MaxStamina);
}
void UMyAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, Health, OldHealth);
}
void UMyAttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, MaxHealth, OldMaxHealth);
}
void UMyAttributeSet::OnRep_Stamina(const FGameplayAttributeData& OldStamina)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, Stamina, OldStamina);
}
void UMyAttributeSet::OnRep_MaxStamina(const FGameplayAttributeData& OldMaxStamina)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, MaxStamina, OldMaxStamina);
}
void UMyAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
// Health를 0 ~ MaxHealth로 Clamp
if (Attribute == GetHealthAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth());
}
}
void UMyAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
// Effect 적용 후 처리
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
// Health가 변경되었을 때
SetHealth(FMath::Clamp(GetHealth(), 0.0f, GetMaxHealth()));
//TODO: Health가 0이면 Death 처리 (나중에)
}
}'내배캠Unreal_TIL > UE' 카테고리의 다른 글
| [TIL] 2026-01-27 | UE UI 애니메이션 및 3D 위젯 구현, 파티클과 사운드 게임 효과 연출 (0) | 2026.01.27 |
|---|---|
| [TIL] 2026-01-26 | UE UI 위젯 설계 (1) | 2026.01.26 |
| [TIL] 2026-01-23 | 캐릭터 에셋 끄적거리기, 리깅이 안되어 있을 때 (4) | 2026.01.23 |
| [TIL] 2026-01-22 | Automata, State Machine (0) | 2026.01.22 |
| [TIL] 2026-01-22 | UE GameplayTags (0) | 2026.01.22 |