Replicated

[Drag Down] 스테미나 자동 회복 시스템 (문제.. 동기화가 느림) 본문

언리얼 엔진/Drag Down (캡스톤 디자인)

[Drag Down] 스테미나 자동 회복 시스템 (문제.. 동기화가 느림)

라구넹 2025. 4. 3. 19:40
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "DDBuffManagerComponent.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class DRAGDOWN_API UDDBuffManagerComponent : public UActorComponent
{
	GENERATED_BODY()

public:	
	UDDBuffManagerComponent();

	void Initailize(class UAbilitySystemComponent* InASC);

protected:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyCategory", meta = (AllowPrivateAccess = "true"))
	TArray< TSubclassOf<class UGameplayEffect> > InitBuffs;

	TObjectPtr<class UAbilitySystemComponent> ASC;
};

// Fill out your copyright notice in the Description page of Project Settings.


#include "ActorComponent/DDBuffManagerComponent.h"
#include "AbilitySystemComponent.h"

// Sets default values for this component's properties
UDDBuffManagerComponent::UDDBuffManagerComponent()
{
	SetIsReplicatedByDefault(true);

	static ConstructorHelpers::FClassFinder<UGameplayEffect> StaminaRegenBuff(TEXT("/Game/Blueprint/GA/GE/BPGE_StaminaRegen.BPGE_StaminaRegen_C"));
	if(StaminaRegenBuff.Succeeded())
	{
		InitBuffs.Emplace(StaminaRegenBuff.Class);
	}

	ASC = nullptr;
}

void UDDBuffManagerComponent::Initailize(UAbilitySystemComponent* InASC)
{
	if (ASC != nullptr) return;

	ASC = InASC;

	for (auto Effect : InitBuffs)
	{
		FGameplayEffectContextHandle Context = ASC->MakeEffectContext();
		FGameplayEffectSpecHandle EffectSpecHandle = ASC->MakeOutgoingSpec(Effect, 1.0f, Context);
		
		if ( EffectSpecHandle.IsValid() )
		{
			ASC->BP_ApplyGameplayEffectSpecToSelf(EffectSpecHandle);
		}
	}
}

일단 버프를 관리해주는 액터 컴포넌트를 만들어준다

Initailize 하면 ASC를 설정하고, InitBuffs에 등록된 버프들을 발동시킨다

 

void ADDCharacterPlayer::SetASC()
{
	if (ASC) return;

	ADDPlayerState* CSPS = GetPlayerState<ADDPlayerState>();
	if (CSPS)
	{
		ASC = CSPS->GetAbilitySystemComponent();
		ASC->InitAbilityActorInfo(CSPS, this);
		ASC->ReplicationMode = EGameplayEffectReplicationMode::Mixed;
		UE_LOG(LogDD, Log, TEXT("*** [NetMode : %d] SetASC, %s, %s"), GetWorld()->GetNetMode(), *GetName(), *GetPlayerState()->GetName());
	}
	else
	{
		UE_LOG(LogDD, Log, TEXT("[NetMode %d] SetASC - ASC Not Found"), GetWorld()->GetNetMode());
	}

	BuffManagerComponent->Initailize(ASC);
}

플레이어의 SetASC에서 Initailize해준다

 

그리고 이펙트는 무한 지속형, Period랑 Magnitude 설정해주자

이럼 Period마다 Magnitude가 가해질 것이다

 

 

근데 문제는 클라이언트 측에서 UI 업데이트가 뚝뚝 끊어진다

예상 이유

Replication이 한 덩어리로 뭉쳐서 와서 느리다

 

로그 찍어보니 정확히 10씩 찬다.

로그를 더 정확히 찍어보자...

 

리플리케이션 뭉치다가 느리게 오는게 맞는 것 같다..

 

 

해결 방안을 생각해보자..

일단 어빌리티에서 사용한 스테미나는 왜 바로바로 깎일까?

그건 예측 실행 덕분이다

 

하지만 현재 액터 컴포넌트는 GAS 외부의 시스템이니 당연히 예측 실행을 지원하지 않는다

그리고 무한 지속 + Period는 예측 실행까진 지원을 안하는 것 같다..

맨 처음 이펙트 실행은 예측할 수 있겠지만 그 이후 주기적으로 실행되는 게 

이것도 예측 실행이 적용되도록 해야겠다

 

어빌리티로 다시 만들자..