1. 속성 세트(Attributes)

특정 캐릭터만 가지고 있는 속성(방어-Def- 무시 공격력), 혹은 모든 캐릭터가 가지는 속성(STR, INT, AGI, DEX 등)을 생성하여 부여할 수 있다.

한 클래스가 여러 세트를 보유할 수도 있다. 이 프로젝트에서는 모든 캐릭터가 동일한 속성 세트를 가지도록 설정한다.

 

 

2. 속성(Attributes)

(1) 특징

- 모든 속성은 부동소수점(float)이다.

- FGameplayAttributeData 구조체에 정의되어있다.

- 게임플레이 이펙트가 속성을 변경할 수 있다.

-> 이를 통해 변화를 예측할 수 있게 된다.

=> 온라인 환경에서 서버가 효과를 추가 계산하지 않아도 됨 -> 성능적 이득

 

(2) 온라인 환경에서의 신뢰성과 딜레이

변화를 예측(계산)하지 못한다면 클라이언트의 요청을 서버에서 받아 그대로 적용해야 하므로 신뢰성에 의문이 생긴다.

- 이로 인한 딜레이가 발생한다.

 

GAS를 이용하면, 속성을 변경할 수 있는 것은 오직 게임플레이 이펙트이므로 신뢰성이 보장된다.

클라이언트에서 잘못된 값으로 변조해도 올바르게 정정해서 적용할 수 있다.

- 서버에서 계산할 필요 없이 효과를 바로 적용할 수 있기 때문에 딜레이도 적다.

 

(3) 자세히 살펴보기

- 기본 값(Base Value) : 액터가 기본으로 가지는 값

- 현재 값(Current Value) : 임시적인 게임플레이 이펙트(버프, 디버프)로 인한 속성의 현재 값


체력 바의 퍼센티지를 나타낼 때는 현재 값을 기본 값으로 나눈 것이 아니라, 최대 체력이라는 속성과 체력이라는 속성의 두 속성간의 관계로 나타내는 것이다.

 

즉, Base Value는 변화되지 않은 기본 값을 뜻하고, Current Value는 게임플레이 이펙트에 의해 변화되거나 변화되지 않은 값을 뜻한다.


 

3. 활용

(1) AuraAttributeSets.h

#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AuraAttributeSet.generated.h"

UCLASS()
class AURA_API UAuraAttributeSet : public UAttributeSet
{
	GENERATED_BODY()

public:
	UAuraAttributeSet();

	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

	// 복제 변수로 지정
	// 서버에서 변수 변경 -> 클라이언트에서 OnRep_Notify 발동
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Vital Attributes")
	FGameplayAttributeData Health;

	UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldHealth) const;
};

 

온라인 환경을 고려하여 체력을 복제하도록 지정할 것이다.

이 때, 'ReplicatedUsing = OnRep_변수 이름' 구문을 사용하여 복제 시에 각 클라이언트에서 해당 노티파이 함수를 호출하도록 한다.

위의 코드와 같이 일반적으로 OnRep_ 이후에는 변수 이름으로 지정한다.


 

- 복제(Replicate) = 동기화(Sync.)

온라인 환경에서 서버에서 어떤 클라이언트의 변경된 값을 다른 클라이언트들에게 전파하는 것.


 

(2) AuraAttributeSets.cpp

#include "AbilitySystem/AuraAttributeSet.h"
#include "AbilitySystemComponent.h"


UAuraAttributeSet::UAuraAttributeSet()
{
}

void UAuraAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const 
{
    // 복제할 때 반드시 오버라이드하여 사용해야 함
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // 조건 노티파이 - 복제된 속성에 사용, 조건 없음, 항상 복제(REPNOTIFY_OnChanged : 변화할 때만 복제)
    DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Health, COND_None, REPNOTIFY_Always);
}


void UAuraAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) const
{
    // Notify 매크로
    GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet, Health, OldHealth);
}

 

- 노티파이 OnRep_Health 함수

노티파이 함수는 UFUNCTION으로 지정되며, 0개의 인수 또는 FGameplayAttributeData 형식의 인수 한 개만 받을 수 있다.

GAMEPLAYATTRIBUTE_REPNOTIFY 매크로를 이용하여 이전 값과 현재 값을 이용하여 서버가 값을 추적할 수 있도록 한다.

 

- GetLifetimeReplicatedProps 함수 오버라이드

복제된 변수를 사용할 때 반드시 오버라이드하여 사용한다.

DOREPLIFETIME_CONDITION_NOTIFY 매크로를 이용하여 Health 속성을 조건 없이 항상 복제하도록 지정한다.

 

 

(3) 속성을 추가하는 순서 정리

1) FGameplayAttribute 타입의 변수 선언

 

2) UPROPERTY로 지정

- ReplicatedUsing = OnRep_변수이름

 

3) OnRep 노티파이 함수 생성

- GAMEPLAYATTRIBUTE_REPNOTIFY 매크로를 이용해 서버가 이전 값을 추적하도록 함

 

4) GetLifeTimeReplicatedProps 함수 오버라이드

- DOREPLIFETIME_CONDITION_NOTIFY 매크로를 이용해 서버가 해당 값을 어떤 조건으로 복제할지 지정

 

위의 하나라도 빠진다면 변수 값이 동기화가 되지 않는 등의 문제가 발생할 수 있으므로 반드시 유의하도록 한다.