본문 바로가기

프로그래밍

🎮 [언리얼 엔진 5] UWorldSubsystem에서 파라미터 복제(Replicate) 구현 방법!

728x90
728x90

 

언리얼 엔진 5에서 UWorldSubsystem 안의 변수를 복제(Replicate)하는 방법을 소개드릴게요.

UWorldSubsystem은 일반적인 액터가 아니라서 DOREPLIFETIME 같은 복제 매크로가 직접 적용되지 않아요. 그래서 약간의 우회적인 방식으로 구현해야 합니다. 아래 내용을 따라 해보시면 쉽게 구현하실 수 있어요 😊


✅ 왜 UWorldSubsystem에서 복제가 어렵나요?

UWorldSubsystem은 AActor가 아니기 때문에:

  • DOREPLIFETIME 사용 불가
  • bReplicates 같은 속성 없음
  • 네트워크를 통해 직접 복제 불가

따라서 복제를 위해서는 복제 가능한 별도의 액터를 만들어서 그 액터를 통해 데이터를 주고받는 방식으로 우회합니다.


✅ Step 1. 복제 가능한 액터 생성하기

AActor를 상속받는 클래스를 하나 만들어줍니다.

// ReplicatedDataActor.h
UCLASS()
class YOURGAME_API AReplicatedDataActor : public AActor
{
    GENERATED_BODY()

public:
    AReplicatedDataActor();

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

    UPROPERTY(ReplicatedUsing = OnRep_MyParam)
    int32 MyParam;

    UFUNCTION()
    void OnRep_MyParam();
};
 
// ReplicatedDataActor.cpp
AReplicatedDataActor::AReplicatedDataActor()
{
    bReplicates = true;
    SetReplicatingMovement(false);
}

void AReplicatedDataActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(AReplicatedDataActor, MyParam);
}

void AReplicatedDataActor::OnRep_MyParam()
{
    // 값 변경 시 처리할 로직
}
 

💡 OnRep_MyParam() 함수는 클라이언트에서 해당 값이 변경되었을 때 호출됩니다!

출처 입력


✅ Step 2. UWorldSubsystem에서 복제된 값 사용하기

UWorldSubsystem 안에서는 위에서 만든 AReplicatedDataActor를 참조해서 복제된 값을 가져옵니다.

// MyWorldSubsystem.h
UCLASS()
class YOURGAME_API UMyWorldSubsystem : public UWorldSubsystem
{
    GENERATED_BODY()

public:
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;

    void SetReplicatedParam(int32 NewValue);
    int32 GetReplicatedParam() const;

private:
    UPROPERTY()
    AReplicatedDataActor* ReplicatedActor;
};
 
// MyWorldSubsystem.cpp
void UMyWorldSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);

    if (GetWorld()->IsServer())
    {
        ReplicatedActor = GetWorld()->SpawnActor<AReplicatedDataActor>();
    }
    else
    {
        TArray<AActor*> Found;
        UGameplayStatics::GetAllActorsOfClass(GetWorld(), AReplicatedDataActor::StaticClass(), Found);
        if (Found.Num() > 0)
        {
            ReplicatedActor = Cast<AReplicatedDataActor>(Found[0]);
        }
    }
}

void UMyWorldSubsystem::SetReplicatedParam(int32 NewValue)
{
    if (ReplicatedActor && GetWorld()->IsServer())
    {
        ReplicatedActor->MyParam = NewValue;
    }
}

int32 UMyWorldSubsystem::GetReplicatedParam() const
{
    return ReplicatedActor ? ReplicatedActor->MyParam : -1;
}
 

✅ 마무리 팁

  • 복제는 항상 서버 → 클라이언트 방향으로만 이루어집니다.
  • ReplicatedActor는 서버에서 반드시 SpawnActor로 생성해야 하고,
  • bAlwaysRelevant = true 설정을 해두면 모든 클라이언트에서 항상 볼 수 있어요.

✅ 결론

UWorldSubsystem 자체는 복제 기능이 없지만, 위처럼 복제 가능한 액터를 통해 데이터를 중계하면 충분히 필요한 기능을 구현할 수 있어요!

조금 번거로워 보일 수 있지만, 서브시스템의 로직은 그대로 유지하면서 네트워크 연동도 유연하게 관리할 수 있어서 아주 유용한 방식입니다

 

 

 

 

728x90
반응형