블루프린트에서의 리플리케이션
지난 두 절에서 우리는 언리얼 엔진의 게임 모드, 스테이트, 컨트롤러, 폰 클래스들이 어떻게 게임의 규칙과 상태, 그리고 플레이어의 조작을 분담하는지 알아보았습니다. 이 모든 클래스들은 특히 멀티플레이어 게임에서 그 진가를 발휘하는데, 이를 가능하게 하는 핵심적인 메커니즘이 바로 리플리케이션(Replication), 즉 네트워크 복제입니다.
이번 절에서는 언리얼 엔진 블루프린트에서 리플리케이션이 어떻게 작동하며, 게임의 상태와 이벤트를 네트워크를 통해 동기화하는 방법에 대해 자세히 알아보겠습니다.
리플리케이션이란 무엇인가?
리플리케이션(Replication) 은 멀티플레이어 게임 환경에서 서버와 클라이언트 간에 게임의 상태(변수, 오브젝트의 위치 등)와 이벤트(함수 호출)를 네트워크를 통해 동기화하는 과정을 의미합니다. 언리얼 엔진은 서버-클라이언트 모델을 기반으로 하며, 서버가 게임의 '진실된' 상태를 소유하고 관리하며, 이 상태를 모든 클라이언트에 복제하여 동기화합니다.
리플리케이션이 필요한 이유
- 게임 상태 동기화: 모든 플레이어의 컴퓨터가 동일한 게임 월드와 상태를 공유해야 합니다. (예: 다른 플레이어의 캐릭터 위치, 아이템 획득 여부, 적의 체력 등)
- 공정한 게임플레이: 서버가 모든 중요한 게임 로직(데미지 계산, 충돌 처리 등)을 처리함으로써 클라이언트 조작(Cheating)을 방지하고 공정한 게임플레이를 보장합니다.
- 효율적인 네트워크 통신: 언리얼 엔진은 필요한 데이터만 효율적으로 복제하여 네트워크 대역폭 사용을 최적화합니다.
블루프린트에서 리플리케이션 설정하기
블루프린트에서 리플리케이션을 설정하는 방법은 크게 세 가지 유형으로 나눌 수 있습니다.
변수 리플리케이션
액터의 특정 변수 값을 서버에서 변경하면, 해당 값이 자동으로 모든 클라이언트에 동기화되도록 설정할 수 있습니다.
변수 생성: 블루프린트에서 복제하고자 하는 변수(예: 플레이어의 Health
, 적의 CurrentAmmo
)를 생성합니다.
리플리케이션 설정: 변수를 선택하고 디테일(Details)
패널의 리플리케이션(Replication)
섹션에서 Replication
드롭다운을 Replicated
로 설정합니다.
적용: 이제 서버에서 이 변수의 값을 변경하면, 클라이언트의 해당 액터 인스턴스에 있는 변수 값도 자동으로 업데이트됩니다.
- 주의:
RepNotify
를 사용하여 변수 값이 복제된 후 특정 로직을 실행할 수 있습니다.
RepNotify (Rep_Notify):
RepNotify
는 Replicated
변수가 클라이언트에 성공적으로 복제되어 값이 변경되었을 때 특정 함수를 자동으로 호출하는 기능입니다. 이를 통해 클라이언트에서 변수 값의 변화에 따른 시각적/청각적 효과를 구현할 수 있습니다.
- 설정: 변수를
Replicated
로 설정한 후, 드롭다운에서Replicated Using
을 선택합니다. 그러면 새로운 함수가 자동으로 생성됩니다. (예:OnRep_Health
) - 활용:
OnRep_Health
함수 내에 체력 바 UI 업데이트, 피격 사운드 재생, 데미지 이펙트 표시 등의 로직을 구현합니다. 이 함수는 서버에서도 호출되지만, 주로 클라이언트의 시각적 피드백을 위해 사용됩니다.
함수 호출 리플리케이션 - RPC
특정 함수가 서버에서 실행되도록 클라이언트가 요청하거나, 서버에서 클라이언트에 특정 함수를 실행하도록 지시할 수 있습니다. 이를 RPC (Remote Procedure Call) 라고 합니다.
함수 세부 정보 패널에서 Replication
섹션의 Replicates
드롭다운을 통해 설정합니다.
Run on Server
(서버에서 실행)
- 클라이언트가 서버에 함수 실행을 요청할 때 사용합니다. (예: 플레이어가 공격 버튼을 눌렀을 때, 클라이언트가 서버에게 "나 공격할게!"라고 알림)
- 설정: 함수를 생성하고
Replicates
를Run on Server
로 설정합니다.Reliable
옵션을 체크하면 네트워크 불안정 시에도 반드시 호출되도록 보장합니다. - 주의:
Run on Server
함수는 오직 소유권(Ownership)을 가진 클라이언트만이 호출할 수 있습니다. 일반적으로PlayerController
와Pawn/Character
가 소유권을 가집니다. 다른 액터(예: 월드에 있는 문)의 함수를 서버에서 실행하고 싶다면, 그 액터에 대한Run on Server
함수를PlayerController
나Pawn
에 만들고, 거기서 다시 해당 액터의 함수를 호출하는 방식으로 우회해야 합니다.
Multicast
(멀티캐스트)
- 서버가 모든 클라이언트에 함수 실행을 지시할 때 사용합니다. (예: 서버가 "모든 클라이언트는 이펙트 재생!"이라고 알림)
- 설정: 함수를 생성하고
Replicates
를Multicast
로 설정합니다.Reliable
옵션을 체크하면 네트워크 불안정 시에도 반드시 호출되도록 보장합니다. - 주의:
Multicast
함수는 오직 서버에서만 호출될 수 있습니다. 클라이언트에서Multicast
함수를 호출하려 하면 경고가 뜨며 작동하지 않습니다. 이 함수는 서버에서도 실행되고, 모든 클라이언트에서도 실행됩니다.
Run on Owning Client
(소유 클라이언트에서 실행)
- 서버가 특정 폰/캐릭터의 소유권을 가진 클라이언트에만 함수 실행을 지시할 때 사용합니다. (예: 서버가 특정 플레이어에게만 "너 데미지 입었어!"라고 알림)
- 설정: 함수를 생성하고
Replicates
를Run on Owning Client
로 설정합니다.Reliable
옵션을 체크하면 네트워크 불안정 시에도 반드시 호출되도록 보장합니다. - 주의: 이 함수는 오직 서버에서만 호출될 수 있으며, 소유권을 가진 클라이언트에서만 실행됩니다.
액터 리플리케이션 (Replicating Actors)
게임 월드에 스폰되는 액터(예: 아이템, 투사체, 적 AI) 자체가 모든 클라이언트에 존재하도록 설정할 수 있습니다.
액터 블루프린트 열기: 복제하고자 하는 액터 블루프린트 (예: BP_PickupItem
)를 엽니다.
리플리케이션 설정: 클래스 디폴트(Class Defaults)
를 클릭하고 디테일(Details)
패널에서 리플리케이션(Replication)
섹션을 찾습니다.
Replicates
: 체크합니다. (이 액터와 그 컴포넌트들이 모든 클라이언트에 복제되도록 허용)Replicate Movement
: 체크합니다. (액터의 위치, 회전, 스케일이 자동으로 복제되도록 함. 폰/캐릭터는 기본적으로 체크되어 있음)Net Update Frequency
: 해당 액터가 초당 몇 번 복제 업데이트를 보낼지 설정합니다. (높을수록 정확하지만 네트워크 부하 증가)
리플리케이션 흐름 및 중요 규칙
언리얼 엔진의 멀티플레이어 환경은 기본적으로 '서버-클라이언트' 모델입니다.
- 서버의 권한: 게임의 모든 핵심 로직, 상태 변경, 물리 시뮬레이션 등은 서버에서만 발생하고 결정됩니다. 클라이언트는 서버의 '복제품'을 가지고 있을 뿐입니다.
- 신뢰성 (Reliable) vs. 비신뢰성 (Unreliable)
- Reliable (신뢰성): 중요한 데이터나 이벤트에 사용합니다. 네트워크 상태가 나쁘더라도 반드시 전달되도록 보장합니다. (재전송 메커니즘 포함)
- Unreliable (비신뢰성): 자주 업데이트되거나 실시간성이 중요한 데이터에 사용합니다. 데이터 손실이 허용되며, 최신 값으로 덮어쓰여지므로 지연이 발생해도 이전 값은 중요하지 않을 때 사용합니다. (예: 캐릭터 위치 업데이트, 프레임마다 변하는 값)
- 오너십 (Ownership)
- 각 폰(Pawn) 은 하나의 컨트롤러(Controller) (플레이어 컨트롤러 또는 AI 컨트롤러)에 의해 소유됩니다.
- 플레이어가 조작하는 폰은 해당 플레이어의 플레이어 컨트롤러가 소유합니다.
Run on Server
RPC는 소유권을 가진 클라이언트만 호출할 수 있습니다.- AI가 제어하는 폰은 서버의 AI 컨트롤러가 소유합니다.
- 소유권은 네트워크 통신 및 권한 부여에 중요한 역할을 합니다.
리플리케이션 예시: 아이템 줍기
플레이어가 아이템을 주웠을 때, 이 아이템이 모든 클라이언트의 월드에서 사라지고, 플레이어의 인벤토리에 추가되는 로직을 리플리케이션으로 구현해봅시다.
BP_PickupItem
(아이템 액터)
클래스 디폴트
에서Replicates
와Replicate Movement
를 체크합니다.- 콜리전 컴포넌트의
On Component Begin Overlap
이벤트에서 로직을 시작합니다. - 이벤트 그래프
On Component Begin Overlap
>Other Actor
를Cast To BP_PlayerCharacter
로 캐스팅합니다.- 캐스팅 성공 시,
Has Authority
노드를 사용하여 현재 코드가 서버에서 실행 중인지 확인합니다. (아이템 줍기 로직은 서버에서만 처리해야 함) Has Authority
가True
일 경우:Run on Server
RPC (예:Server_PickupItem
)를 호출합니다. 이 RPC에BP_PlayerCharacter
와 주운 아이템(Self
참조)을 파라미터로 넘깁니다.
BP_PlayerCharacter
(플레이어 캐릭터)
- 함수 생성:
Server_PickupItem
이라는 커스텀 이벤트를 만들고,Replicates
를Run on Server
로 설정합니다. Server_PickupItem
함수 내부- 아이템을 실제로 플레이어 인벤토리에 추가하는 로직을 구현합니다. (인벤토리 변수 업데이트 등)
- 아이템 액터를
Destroy Actor
노드로 파괴합니다. Multicast
RPC (예:Multicast_PlayPickupEffect
)를 호출하여 모든 클라이언트에 줍기 효과(사운드, 이펙트)를 재생하도록 지시합니다. (서버에서만 호출 가능)
BP_PlayerCharacter
(계속)
- 함수 생성:
Multicast_PlayPickupEffect
라는 커스텀 이벤트를 만들고,Replicates
를Multicast
로 설정합니다. Multicast_PlayPickupEffect
함수 내부- 아이템 줍는 사운드 (
Play Sound at Location
) - 아이템 줍는 이펙트 (
Spawn Emitter at Location
) - 주의: 이 함수는 서버와 모든 클라이언트에서 실행되므로, 이펙트/사운드 재생은
Is Dedicated Server
체크를 통해 전용 서버에서는 건너뛰거나, 필요하다면Is Locally Controlled
체크를 통해 특정 클라이언트에서만 실행되도록 할 수 있습니다.
- 아이템 줍는 사운드 (
이러한 방식으로 서버가 모든 게임 로직을 처리하고, 필요한 정보와 시각적/청각적 피드백을 클라이언트에 복제함으로써 멀티플레이어 환경에서 일관된 게임 경험을 제공할 수 있습니다.
디버깅 팁
Net Mode
변경: 에디터에서플레이(Play)
버튼 옆의 드롭다운을 클릭하여Play As Client
또는Listen Server
모드로 테스트할 수 있습니다.Number of Players
를 늘려 여러 클라이언트를 동시에 실행할 수도 있습니다.- 네트워크 통계: 게임 플레이 중
~
키를 눌러 콘솔을 열고stat net
을 입력하면 네트워크 대역폭 사용량, 패킷 손실률 등 다양한 네트워크 통계 정보를 확인할 수 있습니다. - RPC 호출 확인:
log net
명령어를 통해 네트워크 로그를 활성화하여 RPC 호출 및 변수 복제 흐름을 추적할 수 있습니다. ShowDebug
: AI나 캐릭터의 네트워크 정보를 디버그 드로잉으로 표시할 수 있습니다. (예:showdebug net
또는showdebug all
)
리플리케이션은 멀티플레이어 게임 개발의 핵심이자 가장 복잡한 부분 중 하나입니다. 서버-클라이언트 모델과 각 클래스의 역할, 그리고 리플리케이션의 종류와 규칙을 명확히 이해하는 것이 중요합니다.
이번 절에서는 언리얼 엔진 블루프린트에서 리플리케이션이 어떻게 작동하며, 변수, 함수, 액터의 복제를 통해 게임의 상태와 이벤트를 네트워크를 통해 동기화하는 방법에 대해 알아보았습니다. 리플리케이션은 멀티플레이어 게임의 핵심이자 안정적인 게임플레이를 위한 필수 요소입니다.