UE 5 스터디/Gameplay Ability System(GAS)
23-5. 디버프 - (5) 직렬화
Crat3
2025. 2. 21. 19:10
0. 개요
서버에서 계산한 디버프에 대한 정보를 클라이언트로 복제하기 위해 직렬화한다.
1. 직렬화
(1) AuraAbilityTypes에 멤버 변수 추가
protected:
UPROPERTY()
bool bIsBlockedHit = false;
UPROPERTY()
bool bIsCriticalHit = false;
UPROPERTY()
bool bIsSuccessfulDebuff = false;
UPROPERTY()
float DebuffDamage = false;
UPROPERTY()
float DebuffDuration = false;
UPROPERTY()
float DebuffFrequency = false;
TSharedPtr<FGameplayTag> DamageType;
데미지 부여 시 디버프에 대한 정보를 클라이언트와 통신하기 위해 위의 변수들을 직렬화할 것이다.
bool FAuraGameplayEffectContext::NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess)
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (bIsSuccessfulDebuff)
{
RepBits |= 1 << 9;
}
// 커스텀 변수
if (DebuffDamage > 0.f)
{
RepBits |= 1 << 10;
}
if (DebuffDuration > 0.f)
{
RepBits |= 1 << 11;
}
if (DebuffFrequency > 0.f)
{
RepBits |= 1 << 12;
}
if (DamageType.IsValid())
{
RepBits |= 1 << 13;
}
}
// 14개의 비트 직렬화
Ar.SerializeBits(&RepBits, 14);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (RepBits & (1 << 9))
{
Ar << bIsSuccessfulDebuff;
}
if (RepBits & (1 << 10))
{
Ar << DebuffDamage;
}
if (RepBits & (1 << 11))
{
Ar << DebuffDuration;
}
if (RepBits & (1 << 12))
{
Ar << DebuffFrequency;
}
if (RepBits & (1 << 13))
{
if (Ar.IsLoading())
{
if (DamageType.IsValid() == false)
{
DamageType = TSharedPtr<FGameplayTag>(new FGameplayTag());
}
}
DamageType->NetSerialize(Ar, Map, bOutSuccess);
}
DamageType은 Shared 포인터로 만들어 FGameplayTag를 스마트 포인터로 만들어 저장한다.
(2) Getter와 Setter 함수 선언
// 직렬화를 커스텀하기 위해 반드시 오버라이드
virtual bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess) override;
bool IsCriticalHit() const { return bIsCriticalHit; }
bool IsBlockedHit() const { return bIsBlockedHit; }
bool IsSuccessfulDebuff() const { return bIsSuccessfulDebuff; }
float GetDebuffDamage() const { return DebuffDamage; }
float GetDebuffDuration() const { return DebuffDuration; }
float GetDebuffFrequency() const { return DebuffFrequency; }
TSharedPtr<FGameplayTag> GetDamagedType() const { return DamageType; }
void SetIsCriticalHit(bool bInIsCriticalHit) { bIsCriticalHit = bInIsCriticalHit; }
void SetIsBlockedHit(bool bInIsBlockedHit) { bIsBlockedHit = bInIsBlockedHit; }
void SetIsSuccessfulDebuff(bool bInIsSuccessfulDebuff) { bIsSuccessfulDebuff = bInIsSuccessfulDebuff; }
void SetDebuffDamage(float InDebuffDamage) { DebuffDamage = InDebuffDamage; }
void SetDebuffDuration(float InDebuffDuration) { DebuffDuration = InDebuffDuration; }
void SetDebuffFrequency(float InDebuffFrequency) { DebuffFrequency = InDebuffFrequency; }
(3) 라이브러리에 Getter와 Setter 함수 선언
UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|GameplayEffects")
static bool IsSuccessfulDebuff(const FGameplayEffectContextHandle& EffectContextHandle);
UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|GameplayEffects")
static float GetDebuffDamage(const FGameplayEffectContextHandle& EffectContextHandle);
UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|GameplayEffects")
static float GetDebuffDuration(const FGameplayEffectContextHandle& EffectContextHandle);
UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|GameplayEffects")
static float GetDebuffFrequency(const FGameplayEffectContextHandle& EffectContextHandle);
UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|GameplayEffects")
static FGameplayTag GetDamageType(const FGameplayEffectContextHandle& EffectContextHandle);
bool UAuraAbilitySystemLibrary::IsSuccessfulDebuff(const FGameplayEffectContextHandle& EffectContextHandle)
{
// 커스텀 컨텍스트로 캐스팅
if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
{
return AuraEffectContext->IsSuccessfulDebuff();
}
return false;
}
float UAuraAbilitySystemLibrary::GetDebuffDamage(const FGameplayEffectContextHandle& EffectContextHandle)
{
// 커스텀 컨텍스트로 캐스팅
if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
{
return AuraEffectContext->GetDebuffDamage();
}
return 0.f;
}
float UAuraAbilitySystemLibrary::GetDebuffDuration(const FGameplayEffectContextHandle& EffectContextHandle)
{
// 커스텀 컨텍스트로 캐스팅
if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
{
return AuraEffectContext->GetDebuffDuration();
}
return 0.f;
}
float UAuraAbilitySystemLibrary::GetDebuffFrequency(const FGameplayEffectContextHandle& EffectContextHandle)
{
// 커스텀 컨텍스트로 캐스팅
if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
{
return AuraEffectContext->GetDebuffFrequency();
}
return 0.f;
}
FGameplayTag UAuraAbilitySystemLibrary::GetDamageType(const FGameplayEffectContextHandle& EffectContextHandle)
{
// 커스텀 컨텍스트로 캐스팅
if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
{
if (AuraEffectContext->GetDamagedType().IsValid())
{
return *AuraEffectContext->GetDamagedType();
}
}
return FGameplayTag();
}