RPG Attributes

 

0. 개요

UAuraAttributeSet::UAuraAttributeSet()
{
    InitHealth(50.f);
    InitMaxHealth(100.f);
    InitMana(25.f);
    InitMaxMana(50.f);
}

이전에 속성을 초기화 할 때는 생성자에서 담당했었다.

일반적으로는 게임 플레이 이펙트에서 초기화 하지만 학습의 목적으로 데이터 테이블을 이용하여 속성 값을 초기화 하는 방법에 대해 알아본다.

 

 

1. 기본 속성(Primary Attributes) 추가하기

RPG에서 중요한 스텟을 담당하는 4개의 속성을 추가한다.

	/*
	* Primary 속성
	*/

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Strength, Category = "Primary Attributes")
	FGameplayAttributeData Strength;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Strength);

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Intelligence, Category = "Primary Attributes")
	FGameplayAttributeData Intelligence;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Intelligence);

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Resilience, Category = "Primary Attributes")
	FGameplayAttributeData Resilience;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Resilience);

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Vigor, Category = "Primary Attributes")
	FGameplayAttributeData Vigor;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Vigor);

4개의 속성 데이터를 정의하고 속성 접근자도 등록한다.

OnRep_ 노티파이도 적용하여 복제(Replicate)시 사용할 콜백 함수도 정의한다.

	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldStrength) const;

	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const;

	UFUNCTION()
	void OnRep_Resilience(const FGameplayAttributeData& OldResilience) const;

	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldVigor) const;

 

GetLifetimeReplicatedProps 함수에 새롭게 추가된 속성들에 대해서 복제가 발생하도록 작성한다.

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

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

    // Vital 속성
    DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Health, COND_None, REPNOTIFY_Always);
    DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
    DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Mana, COND_None, REPNOTIFY_Always);
    DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, MaxMana, COND_None, REPNOTIFY_Always);
}

서버에서 속성 값이 변경될 때 클라이언트로 알리는 REPNOTIFY를 설정한다.

void UAuraAttributeSet::OnRep_Strength(const FGameplayAttributeData& OldStrength) const
{
    // Notify 매크로
    GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet, Strength, OldStrength);
}

void UAuraAttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const
{
    // Notify 매크로
    GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet, Intelligence, OldIntelligence);
}

void UAuraAttributeSet::OnRep_Resilience(const FGameplayAttributeData& OldResilience) const
{
    // Notify 매크로
    GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet, Resilience, OldResilience);
}

void UAuraAttributeSet::OnRep_Vigor(const FGameplayAttributeData& OldVigor) const
{
    // Notify 매크로
    GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet, Vigor, OldVigor);
}

- 속성 값 변경 후 복제까지의 과정

속성 값이 변경되어 클라이언트에게 복제되기까지의 순서는 아래와 같다.


 

 

2. ASC(Ability System Component)에 초기 값 데이터 테이블 설정하기 - BP_AuraPlayerState

C++ 코드에서 ASC를 할당한 (Player - AuraPlayerState / Enemy - AuraEnemy) 헤더 파일에서 ASC에 VisibleAnywhere 속성을 추가하면, 디테일 창에서 아래와 같은 메뉴가 노출된다.

 

(1) 데이터 테이블 생성하기

아래와 같이 AttributeMetaData를 행 구조로 하는 데이터 테이블을 생성한다.

행을 추가하고 초기화하려는 속성의 이름과 값을 적고 저장한다.

 

Default Starting Data 항목으로 돌아가서 속성 세트와 테이블을 지정해준다.