2026-06-25 TIL (84일차)
[UE] 프로퍼티 레플리케이션 (Property Replication)
멀티플레이 게임에서 캐릭터의 체력(HP), 탄약 수, 닉네임 같은 중요한 ‘데이터’를 모든 플레이어의 화면에 똑같이 맞추려면 어떻게 해야 할까요? 이때 사용하는 핵심 기술이 바로 프로퍼티 레플리케이션(Property Replication)입니다.
1. 레플리케이션(Replication)의 핵심 원리: “선생님과 학생들”
레플리케이션을 가장 쉽게 이해하려면 ‘칠판에 글을 쓰는 선생님과 받아 적는 학생들’을 떠올리면 됩니다.
- 서버(Authority) = 선생님: 칠판(액터의 속성)에 글을 쓸 수 있는 유일한 권한을 가집니다.
- 클라이언트(Proxy) = 학생: 선생님이 칠판에 쓴 내용을 그대로 자기 노트에 ‘복사(Replication)’해서 적습니다.
- 단방향 동기화: 학생(클라이언트)이 자기 노트에 마음대로 체력을 999로 고쳐 적는다고 해서 칠판(서버)의 내용이 바뀌지 않습니다. 복제는 무조건 서버 ➡️ 클라이언트로만 발생합니다.
2. RPC vs 프로퍼티 레플리케이션 (언제 무엇을 쓸까?)
앞서 배운 RPC와 헷갈리기 쉽습니다. 두 가지는 명확한 역할 차이가 있습니다.
| 구분 | RPC (Remote Procedure Call) | Property Replication (프로퍼티 복제) |
|---|---|---|
| 특징 | “행동/이벤트” (순간적으로 발생하고 끝남) | “상태/데이터” (지속적으로 유지됨) |
| 예시 | 총 쏘기, 점프하기, 폭발 이펙트 재생 | 현재 체력(HP), 총알 개수, 플레이어 닉네임 |
| 중간 난입 | 늦게 접속한 사람은 폭발 이펙트를 못 봄 | 늦게 접속해도 깎인 체력(HP) 상태를 바로 전달받음 |
결론: “게임 진행에 필수적인 데이터 상태”를 유지해야 한다면 무조건 프로퍼티 레플리케이션을 써야 합니다!
3. 💻 프로퍼티 레플리케이션 C++ 설정 3단계
C++에서 특정 변수(프로퍼티)를 복제하려면 반드시 다음 3단계를 거쳐야 합니다. (하나라도 빠지면 작동하지 않습니다!)
1️⃣ 액터 자체의 복제 허용 (bReplicates)
액터의 속성을 복제하려면, 먼저 그 액터 자체가 네트워크를 타고 넘어갈 수 있는 존재여야 합니다. 생성자(Constructor)에서 설정합니다.
1
2
3
4
5
6
// MyActor.cpp
AMyActor::AMyActor()
{
// 이 액터는 서버에서 클라이언트로 복제됩니다!
bReplicates = true;
}
2️⃣ 복제할 변수에 Replicated 키워드 달기
헤더 파일(.h)에서 동기화하고 싶은 변수의 UPROPERTY 안에 키워드를 추가합니다
1
2
3
// MyActor.h
UPROPERTY(Replicated)
float CurrentHealth; // 이 변수의 변화를 클라이언트에게 뿌려주겠다!
GetLifetimeReplicatedProps 함수 등록 (가장 중요!)
엔진에게 “이 변수를 네트워크 통신에 포함시켜라”라고 명시적으로 등록하는 과정입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// MyActor.cpp
// 1. 반드시 네트워크 헤더를 추가해야 합니다.
#include "Net/UnrealNetwork.h"
// 2. 함수 오버라이딩 구현
void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// 3. DOREPLIFETIME 매크로를 사용해 변수 등록
// 형식: DOREPLIFETIME(클래스명, 변수명);
DOREPLIFETIME(AMyActor, CurrentHealth);
}
이제 서버에서 CurrentHealth 값을 변경하면, 0.1초도 안 돼서 모든 클라이언트의 CurrentHealth 값도 똑같이 변경됩니다!
4. 심화: 값이 바뀌었을 때 UI를 업데이트 하려면? (RepNotify)
단순히 값만 복제되는 것에서 끝나는 게 아닙니다. “체력이 깎였으니(값 변경), 피격 애니메이션을 틀고 체력바 UI를 줄여라!” 같은 처리가 필요하죠. 이때 쓰는 마법의 키워드가 ReplicatedUsing (RepNotify) 입니다.
1
2
3
4
5
6
7
// 헤더 파일 (.h)
// 값이 복제되어 도착하면 "OnRep_CurrentHealth" 함수를 실행해라!
UPROPERTY(ReplicatedUsing = OnRep_CurrentHealth)
float CurrentHealth;
UFUNCTION()
void OnRep_CurrentHealth(); // 반드시 UFUNCTION()이 붙어야 합니다.
서버가 체력을 50으로 바꾸면 ➡️ 클라이언트로 50이라는 값이 복제됨 ➡️ 클라이언트 컴퓨터에서 자동으로 OnRep_CurrentHealth() 함수가 실행되어 UI를 업데이트합니다.