[UE5] GAS (2)

GamzaTori·2024년 11월 27일

UE5 C++

목록 보기
26/27

Gameplay Attribute

  • 캐릭터의 상태를 나타내는 값으로 예를 들어 체력, 마나, 스태미나같은 스탯이 있습니다.
  • 속성은 능력이나 효과의 영향을 받으며 게임 내 캐릭터의 능력 발동과 직접적으로 연결됩니다.
  • 지금은 캐릭터 클래스에서 Hp 같은 스탯을 관리하지만 GameplayAttribute를 이용해 관리합니다.

AttributeSet을 상속받은 클래스 생성

  • 몬스터와 캐릭터들에만 존재하는 스탯이 있는 경우 해당 클래스를 상속받아 따로 관리할 수 있다.
  • 만든 클래스를 상속받아 몬스터와 플레이어의 AttributeSet 생성
// h
#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 할 수 있도록 한다
// MyAttributeSet.h
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;
    
// cpp
UMyAttributeSet::UMyAttributeSet()
{
	InitHealth(100.0f);
	InitMaxHealth(100.0f);
    
    // GetHealth();
    // SetHealth(100.0f);
}
  • FGameplayAttributeData는 Base와 Current 2가지의 값을 float으로 가지고 있다.
  • ATTRIBUTE_ACCESSORS 매크로를 이용해 get, set, init에 대한 함수를 모두 만든 것과 같다.
  • InitHealth와 같은 함수를 사용할 수 있는 이유가 매크로를 통해 만들어주었기 때문에 가능하다.

캐릭터에 AttributeSet 추가

protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	TObjectPtr<class UMyAttributeSet> AttributeSet;
  • 플레이어의 경우 PlayerState에서 생성해 AbilitySystemComponent와 생명주기를 같이한다.
// PlayerState.h
public:
	UMyAbilitySystemComponent* GetMyAbilitySystemComponent() const;
	UMyPlayerSet* GetMyPlayerSet() const;
    
protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	TObjectPtr<class UMyPlayerSet> PlayerSet;
    
// cpp
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의 다양한 옵션을 통해 효과를 설정할 수 있다
profile
게임 개발 공부중입니다.

0개의 댓글