[Unreal Engine] Replication

Imeamangryang·2025년 7월 29일
post-thumbnail

출처 ㅣ Cedric Neukirchen - Multiplayer Network Compendium


Replication

'Replication'이란 무엇인가?

복제(Replication)는 서버가 정보를 클라이언트로 전달하는 행위입니다.
이 동작은 특정 엔티티나 그룹에 한정될 수 있습니다. 블루프린트에서는 주로 해당 AActor의 복제 설정에 따라 복제가 이루어집니다.

속성 복제가 가능한 첫 번째 클래스는 AActor입니다. UObject도 복제가 가능하지만, 반드시 AActor를 통해 복제되어야 하며, 복제를 처리할 AActor가 필요합니다.
AActor를 통해 별다른 추가 작업 없이 복제할 수 있는 UObject의 좋은 예는 UActorComponent입니다.

앞서 언급한 모든 클래스는 어느 시점에서든 AActor를 상속받아 필요하다면 속성 복제가 가능합니다. 하지만 모든 클래스가 동일한 방식으로 복제되는 것은 아닙니다.
예를 들어, AGameMode는 전혀 복제되지 않으며 서버에만 존재합니다. AHUD는 클라이언트에만 존재하고 역시 복제되지 않습니다.

액터의 'Replication'을 사용(설정)하는 방법

Replication은 AActor 자식 클래스의 Class Defaults 또는 생성자에서 활성화할 수 있습니다.

ATestCharacter::ATestCharacter(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    bReplicates = true;
    bReplicateMovement = true;
}

'bReplicates'가 TRUE로 설정된 액터는 서버에서 생성될 경우 모든 클라이언트에 복제되어 생성됩니다. 그리고 반드시 서버에서 생성된 경우에만 복제됩니다.

클라이언트가 이 액터를 생성하면 해당 액터는 그 클라이언트에만 존재하게 됩니다.

프로퍼티의 'Replication'을 사용(설정)하는 방법

Replication이 활성화되면 액터 내부의 변수를 Replication할 수 있습니다. 이를 수행하는 방법에는 여러 가지가 있으며, 가장 기본적인 방법부터 살펴보겠습니다.

“Replication” 드롭다운 메뉴를 “Replicated”로 설정하면 이 변수는 이 액터의 모든 복제된 인스턴스에 복제됩니다.

변수는 특정 조건에서만 복제될 수 있습니다. 이에 대해서는 조금 더 뒤에서 다루겠습니다.

복제되는 변수는 두 개의 흰색 원 아이콘으로 표시됩니다.

C++에서 변수를 복제하려면 약간의 추가 작업이 필요합니다.

// 복제될 Health 변수 생성
UPROPERTY(Replicated)
float Health;

.cpp 파일에는 GetLifetimeReplicatedProps 함수가 필요합니다. 이 함수의 헤더 선언은 변수를 복제하도록 지정하면 UE에서 자동으로 생성해줍니다.

이 함수 내에서 복제할 변수와 복제 규칙을 정의할 수 있습니다.

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

    // 복제할 변수를 여기에 나열합니다
    DOREPLIFETIME(ATestPlayerCharacter, Health);
}

조건부 복제도 가능합니다:

// 이 오브젝트/클래스의 소유자에게만 변수를 복제합니다
DOREPLIFETIME_CONDITION(ATestPlayerCharacter, Health, COND_OwnerOnly);
조건(Condition)설명(Description)
COND_InitialOnly이 속성은 최초 전송 시에만 전송을 시도합니다.
COND_OwnerOnly이 속성은 액터의 소유자에게만 전송됩니다.
COND_SkipOwner이 속성은 소유자를 제외한 모든 연결에 전송됩니다.
COND_SimulatedOnly이 속성은 시뮬레이션된 액터에게만 전송됩니다.
COND_AutonomousOnly이 속성은 자율 액터(autonomous actors)에게만 전송됩니다.
COND_SimulatedOrPhysics이 속성은 시뮬레이션되었거나 bRepPhysics가 설정된 액터에게 전송됩니다.
COND_InitialOrOwner이 속성은 최초 전송 시 또는 액터의 소유자에게 전송됩니다.
COND_Custom이 속성은 특정 조건이 없으며, SetCustomIsActiveOverride를 통해 동적으로 제어할 수 있습니다.

복제 과정 전체는 서버에서 클라이언트로만 동작하며, 그 반대는 불가능하다는 점을 이해하는 것이 중요합니다.

클라이언트가 다른 클라이언트와 공유하고 싶은 정보를 서버가 복제하도록 만드는 방법(예: PlayerName)은 이후에 다루겠습니다.

변수를 복제하는 또 다른 방법은 "ReplicatedUsing"으로 표시하는 것입니다. 블루프린트에서는 이를 "RepNotify"라고 하며, 변수의 새로운 값이 클라이언트에 복제될 때 호출되는 함수를 지정할 수 있습니다.

블루프린트에서는 "Replication" 드롭다운 메뉴에서 “RepNotify”를 선택하면 이 함수가 자동으로 생성됩니다.

C++ 버전은 약간의 추가 작업이 필요하지만 동작 방식은 동일합니다.

// RepNotify Health 변수 생성
UPROPERTY(ReplicatedUsing=OnRep_Health)
float Health;

// OnRep 함수 생성 | UFUNCTION() 매크로가 중요! | virtual일 필요는 없음
UFUNCTION()
virtual void OnRep_Health();
void ATestCharacter::OnRep_Health()
{
    if (Health <= 0.f)
    {
        PlayDeathAnimation();
    }
}

ReplicatedUsing=FUNCTIONNAME을 사용하면 변수가 성공적으로 복제될 때 호출할 함수를 지정할 수 있습니다. 이 함수에는 'UNFUNCTION()' 매크로가 필요하며, 매크로가 비어 있어도 반드시 선언해야 합니다.

  • C++와 블루프린트의 RepNotify 차이점

여기서 중요한 점은 C++와 블루프린트가 RepNotify를 약간 다르게 처리한다는 것입니다. C++에서는 RepNotify 함수가 클라이언트에서만 호출됩니다.

서버에서 값을 변경하고 OnRep 함수도 호출해야 할 경우, 변수를 조정한 후 직접 호출해야 합니다. OnRep 함수는 변수가 클라이언트에 복제될 때 호출되는 콜백이기 때문입니다.

반면 블루프린트에서는 OnRep 함수가 클라이언트와 서버 모두에서 호출됩니다. 블루프린트 버전의 OnRep는 "Property Changed" 콜백이기 때문입니다. 즉, 서버에서도 호출되고, 클라이언트가 변수를 로컬로 변경해도 호출됩니다.

profile
언리얼 엔진 주니어(신입) 개발자 | 소설 쓰는 취준 개발자

0개의 댓글