본문 바로가기

Replication Condition

@iamrain2025. 10. 24. 17:33

 언리얼 엔진의 리플리케이션(Replication, 복제)은 서버의 액터와 프로퍼티 상태를 클라이언트와 동기화하는 프로세스다.

기본적으로 프로퍼티는 값이 변경될 때마다 연결된 모든 클라이언트로 복제된다. 하지만 모든 프로퍼티를 항상 모든 클라이언트에게 전송하는 것은 네트워크 대역폭의 낭비이며, 게임의 확장성을 저해하는 주요 요인이 될 수 있다.

 리플리케이션 조건(Replication Condition)은 특정 프로퍼티가 어떤 조건 하에서, 그리고 어떤 클라이언트에게 복제될지를 세밀하게 제어하는 메커니즘이다. 개발자는 네트워크 트래픽을 최적화하고, 각 클라이언트에게 정말로 필요한 데이터만을 전송하여 효율적인 멀티플레이어 환경을 구축할 수 있다.

1. 작동 원리 및 주요 함수

리플리케이션 조건은 AActor 클래스의 GetLifetimeReplicatedProps 함수 내에서 설정된다. 이 함수는 액터의 생명주기 동안 어떤 프로퍼티를 어떻게 복제할지 정의하는 역할을 한다.

// MyActor.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Net/UnrealNetwork.h" // DOREPLIFETIME 매크로를 위해 필요
#include "MyActor.generated.h"

UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

public:
    AMyActor();

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

    UPROPERTY(Replicated)
    float Health;

    UPROPERTY(ReplicatedUsing = OnRep_Ammo)
    int32 Ammo;

    // 소유자에게만 복제될 프로퍼티
    UPROPERTY(Replicated)
    int32 SecretData;

    UFUNCTION()
    void OnRep_Ammo();
};

// MyActor.cpp
#include "MyActor.h"

AMyActor::AMyActor()
{
    bReplicates = true; // 액터가 복제를 사용하도록 설정
}

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

    // Health 프로퍼티는 조건 없이 항상 복제 (값이 바뀔 때)
    DOREPLIFETIME(AMyActor, Health);

    // Ammo 프로퍼티는 조건 없이 항상 복제
    DOREPLIFETIME(AMyActor, Ammo);

    // SecretData는 소유자(Owner)에게만 복제
    DOREPLIFETIME_CONDITION(AMyActor, SecretData, COND_OwnerOnly);
}

void AMyActor::OnRep_Ammo()
{
    // Ammo 값이 서버로부터 복제되었을 때 클라이언트에서 호출됨
}
  • DOREPLIFETIME(ClassName, PropertyName): 가장 기본적인 매크로로, 해당 프로퍼티를 복제 목록에 추가한다. 값이 변경될 때마다 모든 클라이언트에게 복제된다.
  • DOREPLIFETIME_CONDITION(ClassName, PropertyName, Condition): 지정된 Condition을 만족할 때만 프로퍼티를 복제한다. 네트워크 최적화의 핵심적인 역할을 한다.

2. 주요 리플리케이션 조건

조건 설명 주요 사용 사례
COND_None 조건 없음. DOREPLIFETIME과 동일하게 항상 변경 시 복제. 일반적인 데이터 동기화.
COND_InitialOnly 액터가 클라이언트에 처음 스폰될 때 단 한 번만 전송. 게임 도중 절대 변하지 않는 프로퍼티 (예: 캐릭터 종류, 스킨 ID).
COND_OwnerOnly 액터의 소유자(Owner)인 클라이언트에게만 복제. 1인칭 시점의 총알 수, 플레이어의 개인 인벤토리 정보 등.
COND_SkipOwner 액터의 소유자를 제외한 모든 클라이언트에게 복제. 소유자는 이미 예측한 결과(예: 발사 이펙트)를 다시 받을 필요 없을 때.
COND_SimulatedOnly 서버의 ROLE_Authority를 제외하고, 클라이언트의 ROLE_SimulatedProxy에게만 복제. 다른 플레이어의 캐릭터 애니메이션 상태와 같이, 시뮬레이션되는 액터에만 필요한 정보.
COND_AutonomousOnly 클라이언트의 ROLE_AutonomousProxy에게만 복제. 플레이어가 직접 조종하는 캐릭터의 서버 조정값(예: 서버가 강제로 수정한 위치).
COND_SimulatedOrPhysics SimulatedProxy 또는 물리 시뮬레이션 중인 액터에게 복제. 물리 객체의 동기화에 사용.
COND_ReplayOrDemo 리플레이 또는 데모 재생 중에만 복제. 리플레이 시스템에만 필요한 디버깅 정보나 추가 데이터.
COND_Custom 사용자 정의 조건을 사용할 때 지정. DOREPLIFETIME_ACTIVE_OVERRIDE와 함께 사용. 복잡한 게임 로직에 따라 복제 여부를 동적으로 결정해야 할 때.

3. 사용자 정의 조건 (COND_Custom)

COND_Custom을 사용하면 개발자가 직접 정의한 C++ 코드를 통해 특정 프로퍼티의 복제 여부를 동적으로 결정할 수 있다.

DOREPLIFETIME_ACTIVE_OVERRIDE 매크로와 함께 사용된다.

// MyActor.h
// ...
public:
    // ...
    UPROPERTY(Replicated)
    bool bIsSpecialEffectActive;

    bool bHasSpecialItem; // 이 값은 게임 로직에 따라 변경됨

// MyActor.cpp
// ...
void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // ...

    // bHasSpecialItem이 true일 때만 bIsSpecialEffectActive를 복제
    DOREPLIFETIME_CONDITION_NOTIFY(AMyActor, bIsSpecialEffectActive, COND_Custom, REPNOTIFY_Always);
}

// bIsSpecialEffectActive 프로퍼티의 복제 여부를 결정하는 함수
void AMyActor::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
{
    Super::PreReplication(ChangedPropertyTracker);

    // DOREPLIFETIME_ACTIVE_OVERRIDE(클래스, 프로퍼티, 활성화 여부)
    DOREPLIFETIME_ACTIVE_OVERRIDE(AMyActor, bIsSpecialEffectActive, bHasSpecialItem);
}
  • PreReplication 함수는 액터가 복제를 위해 처리되기 직전에 호출됨.
  • DOREPLIFETIME_ACTIVE_OVERRIDE 매크로를 사용하여 bIsSpecialEffectActive 프로퍼티의 복제 활성화 상태를 bHasSpecialItem 변수의 값에 따라 동적으로 설정함.

4. 내부 구현 및 계층 구조

  1. 사용자 코드 계층 (Application Layer)
    • 개발자가 C++ 헤더 파일에서 UPROPERTY(Replicated)로 프로퍼티를 선언하고, .cpp 파일의 GetLifetimeReplicatedProps에서 DOREPLIFETIME_CONDITION으로 조건을 명시한다.
  2. 언리얼 헤더 툴 (Unreal Header Tool - UHT)
    • 컴파일 이전 단계에서 UHT가 소스 코드를 파싱하여 UPROPERTY, UFUNCTION 등의 매크로를 분석한다.
    • generated.cpp 파일에 리플리케이션 관련 메타데이터와 함수 구현을 자동으로 생성한다. 이 정보는 런타임에 엔진이 사용한다.
  3. 엔진 - 리플리케이션 시스템 계층 (Engine - Replication System)
    • UNetDriver: 네트워크 연결과 데이터 전송을 총괄하는 핵심 클래스. 각 클라이언트 연결(UNetConnection)을 관리한다.
    • UActorChannel: 서버와 특정 클라이언트 간의 한 액터에 대한 복제 통신 채널. 서버는 복제해야 할 모든 액터에 대해 각 클라이언트 연결마다 하나의 액터 채널을 가진다.
    • FObjectReplicator / FPropertyReplicator: 특정 오브젝트와 프로퍼티의 복제를 담당하는 내부 클래스.
    • 복제 과정:
      1. 서버의 UNetDriver가 매 틱마다 클라이언트로 보낼 데이터를 수집함. (UNetDriver::ServerReplicateActors)
      2. 각 클라이언트 연결(UNetConnection)에 대해, 해당 클라이언트와 관련된 액터 목록을 순회함.
      3. 각 액터에 대해 UActorChannel::ReplicateActor() 함수가 호출됨.
      4. ReplicateActor() 내부에서, 액터의 GetLifetimeReplicatedProps를 통해 설정된 복제 목록을 가져옴.
      5. 목록의 각 프로퍼티에 대해 RepLayout->ReplicateProperties()가 호출되며, 여기서 리플리케이션 조건(ELifetimeCondition)이 평가됨.
      6. 예를 들어, 조건이 COND_OwnerOnly라면, 현재 처리 중인 UNetConnection이 해당 액터의 소유자인지 확인함. (Connection->OwningActor == Actor)
      7. 조건 평가를 통과하면, 프로퍼티의 현재 값이 마지막으로 이 클라이언트에 보냈던 값과 다른지 비교함. (Change-detection)
      8. 값이 다르다면, 프로퍼티의 데이터를 FNetBitWriter를 사용해 비트 스트림으로 직렬화하여 패킷에 씀.
  4. 네트워크 전송 계층 (Network Transport Layer)
    • 직렬화된 데이터가 포함된 패킷은 UDP 프로토콜을 통해 해당 클라이언트로 전송된다.

6. 요약

 리플리케이션 조건은 언리얼 엔진에서 특정 프로퍼티가 어떤 클라이언트에게, 그리고 어떤 상황에서 복제될지를 결정하는 규칙입니다. 기본적으로 프로퍼티는 값이 바뀔 때마다 모든 클라이언트에게 전송되는데, 이는 불필요한 네트워크 트래픽을 유발할 수 있습니다.

리플리케이션 조건을 사용하면 예를 들어 '오직 소유자에게만(COND_OwnerOnly)' 또는 '초기 스폰 시에만(COND_InitialOnly)'과 같이 복제 규칙을 세밀하게 제어하여 네트워크 대역폭을 크게 최적화할 수 있습니다. 이는 효율적이고 확장성 있는 멀티플레이어 게임을 만드는 데 필수적인 기능입니다.

 

 대표적으로 COND_OwnerOnly, COND_SkipOwner, COND_InitialOnly가 있습니다.

  • COND_OwnerOnly는 플레이어의 총알 수나 개인 점수처럼 해당 플레이어만 알아야 하는 데이터를 복제할 때 사용합니다.
  • COND_SkipOwner는 발사 이펙트처럼 소유자는 이미 클라이언트 측에서 예측했으므로 굳이 다시 받을 필요 없는 데이터를 다른 플레이어에게만 전송할 때 유용합니다.
  • COND_InitialOnly는 캐릭터의 종족이나 외형처럼 게임 도중 절대 변하지 않는 값을 액터가 처음 생성될 때 한 번만 보내 대역폭을 절약하기 위해 사용합니다.

'Unreal' 카테고리의 다른 글

Remote Procedure Call  (0) 2025.10.27
NetRole  (0) 2025.10.27
언리얼 엔진 리플리케이션 Replication  (1) 2025.10.24
언리얼 엔진 리플렉션 시스템 Unreal Engine Reflection System  (0) 2025.10.23
UE5 Cast의 내부 동작 원리  (0) 2025.10.22
iamrain
@iamrain :: Annals of Unreal

iamrain 님의 블로그 입니다.

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차