본문 바로가기
언리얼_엔진_게임개발_공부/언리얼 네트워크

언리얼 엔진의 네트워크 / NetMode / Replication

by jaboy 2025. 3. 12.

https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine#actorreplication

언리얼 엔진에서 서버-클라이언트 통신하는 방법에 대해 강의를 들으며 추가로 참고한 위 링크에서 중요하다고 생각되는 내용을 정리할 것이다.

 

서버-클라이언트 관계 개요

멀티플레이어 게임에서는 실제로 게임이 플레이되는 유일한 authoritative 게임 스테이트가 서버에 존재한다.

클라이언트의 로컬 폰에서 서버에 존재하는 원격 폰으로 Remote Procedure Call (RPC) 을 보내 인게임 행동을 한다.

서버는 게임스테이트 정보를 각 클라이언트로 복제한다. 이 정보는 액터의 위치, 행동 규칙, 변수 값 등을 담고 있다.

클라이언트는 이렇게 서버에서 받은 정보를 바탕으로 서버의 상태를 approximate (근사치 바탕으로 모방?)한다.

 

+ 기본적으로 서버는 비주얼을 직접 클라이언트에 보내지 않고 상태 정보만 게임 인스턴스에 보낸다.

클라이언트의 게임 인스턴스 안에서 이 정보가 재-시각화된다.

 

+ 앞으로 계속 사용할 authoritative 는 서버에 존재하는, 실제 게임플레이가 이루어지는 버전?을 지칭한다.

네트워크 멀티플레이어 게임플레이 예시

1. Player 1이 로컬에서 공격 버튼 입력

  1) Player 1 로컬 폰 --> 서버 폰 : 공격 명령 릴레이

  2) 서버 무기 : 프로젝타일 스폰

  3) 서버 --> 각 클라이언트 : 클라이언트 내 프로젝타일의 카피를 생성하도록 알림

  4) 서버 무기 --> 각 클라이언트 : 공격 사운드와 vfx 재생하도록 알림

2. Player 1 Projectile (서버) 이 전방으로 이동

  1) 서버 --> 각 클라이언트 : 클라이언트 내 프로젝타일의 이동을 복제하도록 알림

3. Player 1 Projectile 이 Player 2 와 충돌 (서버)

  1) 서버 내 : 충돌 시 프로젝타일 destroy 함수 트리거

  2) 서버 --> 각 클라이언트 : 클라이언트 내 프로젝타일 카피 destroy하도록 알림 (자동)

  3) 서버 --> 각 클라이언트 : 충돌 시 클라이언트에 사운드/비주얼 재생하라고 알리는 함수 트리거

  4) Player 2 서버 폰 : 대미지 입음

  5) Player 2 서버 폰 --> Player 2 클라이언트 : 피격 화면 효과 재생 알림

 

위와 같은 상호작용은 네트워크를 통해 아래와 같은 여러 다른 월드에서 일어난다.

- 서버의 Authoritative 월드

- Player 1 클라이언트 월드

- Player 2 클라이언트 월드

- 그 외 서버의 게임 인스턴스에 연결된 다수의 클라이언트 월드 

 

각 월드는 각자만의 플레이어 컨트롤러, 폰, 무기, 프로젝타일 등을 갖고 있으므로, 서버에서 실제로 플레이되는 게임 이벤트들을 각 클라이언트가 시청각적으로 정확히 나타기 위해서 서버의 이벤트를 정확히 복제해야 한다.

이러한 프로세스를 고려하면 게임플레이 상호작용 (충돌, 이동, 공/피격) 과 장식적 효과 (vfx, 사운드, HUD) 가 나뉘게 된다. 개발자는 어떤 정보가 어떤 클라이언트로 복제되는지 지정하여 모든 플레이어가 일관된 경험을 하는 동시에 네트워크의 대역폭이 과부하되지 않도록 만들어야 한다.

 

네트워크 모드

: 네트워크 게임 세션에 있어 기계 (PC 등) 가 맺는 관계성

모드 ENetMode:: 설명
Standalone NM_Standalone - 로컬 전용.
- 클라이언트/서버의 기능 모두 포함하나 원격 클라이언트의 연결 불허.
- 싱글플레이어 또는 로컬 멀티플레이어 에서 사용.

- 서버와 클라이언트의 기능을 모두 하므로, 멀티플레이어 로직은 추가 작업 없이 single-player standalone network mode 에서 작동 가능
Dedicated Server NM_DedicatedServer - 서버 전용.
- 원격 클라이언트의 연결만 허용되며 그래픽, 사운드, 입력 등 플레이어-중심 기능은 모두 제외함.
- 안정성이 필요하거나 대규모 멀티플레이어 게임의 경우 활용하는 모드.

- 다른 플레이어들로부터 분리된 기계와 연결이 필요하여 리슨 서버보다 비용이 크고 세팅이 복잡함.
- 모든 플레이어가 원격으로 연결되므로 보다 일관된 / 공정한 경험을 할 수 있음.
- 그래픽을 렌더하거나 로컬 플레이어에만 적용되는 로직은 제외하므로 서버 로직 수행에 있어 효율적임.
Listen Server NM_ListenServer - 게임을 호스팅하는 로컬 플레이어를 가진 서버.
- 네트워크 상 다른 플레이어들에 노출.
- 캐주얼 협동/경쟁 게임에 사용.

- 동일한 기계에서 리슨 서버를 시작하고 게임을 플레이할 수 있어 사용자 입장에서 간편

- 리슨 서버를 호스팅하는 플레이어의 경우 직접 그 서버에서 플레이하게 되므로 어드밴티지가 있다고 할 수 있음.

- 한편, 서버를 호스팅하는 추가적인 작업을 동시에 수행하므로 디스어드밴티지가 있다고 할 수도 있음.
--> 완전한 공정성이 매우 중요하거나 네트워크 로드가 많은 게임에는 부적합.
Client  NM_Client - 원격 서버에 연결되는 클라이언트 전용. 서버 로직 제외.

 

Replication

: authoritative 서버가 연결된 클라이언트로 상태 데이터를 보내 서버의 게임 상태를 복제하도록 하는 것.

: Replication 설정이 알맞게 되어 각기 다른 기계의 게임 인스턴스들이 동기화될 수 있게 하는 것이 목표

 

- AActor 베이스 클래스들은 상태가 잘 복제될 수 있도록 디자인 되어 있음. 

- UObject 베이스 클래스들은 복제가 가능하나 액터에 subobject 로 부착되어야 적절하게 복제될 수 있음.

 

언리얼의 Replication 은 크게 두 가지로 볼 수 있다.

 

1. Actor Replication

- 객체의 replicate + replicate 되어야 하는 프로퍼티들의 지정 + 네트워크 통해 호출될 함수의 정의

2. Replication Systems

- 객체를 정확한 목적지로 replicate 하는 작업을 담당하는 내부 시스템

 

Actor Replication

Actor 는 여러 메커니즘을 통해 네트워크를 건너 상호작용하는데, 다음과 같은 주요 방식들이 있다.

- Replicated Properties

: 네트워크 건너로 replicate 되는 액터의 프로퍼티들

- Replicated Using Properties

: 네트워크 건너로 replicate 되는 액터의 프로퍼티들 + replicate 직후 지정된 함수를 호출

- Remote Procedure Calls (RPC)

: 액터가 한 기계에서 특정 함수를 호출하고 다른 기계에서 함수가 실행되게 하는 기능

: 예를 들어 액터가 클라이언트 내의 서버 RPC 를 호출하면 해당 네트워크 패킷을 받은 서버에서 함수가 실행

 

actor replication 은 다음과 같은 주요 단계를 포함한다.

- 클라이언트에서 어떤 액터가 어느 연결에 replicate 되어야 하는지 지정 (참고)

- 서버에서 프로퍼티 업데이트 및 RPC 실행 순서 결정 (참고)

- 서버에서 연결된 클라이언트로 관련 정보 전달

 

대부분의 액터는 기본적으로 replicate 되지 않고 로컬에서만 작동하게 되어 있다.

따라서 C++ 에서 bReplicates 변수를 set 하거나 블루프린트에서 Replicates 값을 변경해주어야 한다.

액터와 프로퍼티를 replicate 하는 방법에 대해서는 여기를 참고... (이 내용은 내일 정리해보아야겠다)

 

기능별 Replicate 방식 정리

기능 / 요소 설명 자동 여부
Creation / Destruction - 서버에 authoritative 액터가 스폰되면, 연결된 클라이언트에 원격 proxy 를 만듦
- replicate 할 정보는 이 proxy 에 전달
- authoritative 액터가 destroy 되면 원격 proxy 를 자동으로 destroy
자동
Movement authoritative 액터에 bReplicateMovement = true 로 설정하면 위치, 회전, 속도가 자동으로 replicate 자동
Properties UPROPERTY Replicated 또는 ReplicatedUsing 지정된 프로퍼티는 값이 변경될 때 자동 replicate 수동
Components - 액터 컴포넌트는 액터가 replicate 되는 경우 액터의 일부로 replicate
- 컴포넌트 내 Replicated 지정된 변수값 또한 replicate
- 컴포넌트 내 RPC 호출은 액터의 RPC 호출과 일관되게 작동 (무슨 말이지..?)
수동
Subobjects UObject 기반 객체는 액터에 부착되면 subobject로서 replicate 수동
RPCs - 특정 기기로 전달되는 함수로, RPC를 호출한 기기에 관계 없이 목적지 기기에서만 실행
- 목적지 기기는 Server, Client, NetMulticast 로 지정 가능
- Server : 서버에서만 실행
- Client : 액터의 owning 클라이언트에서만 실행
- NetMulticast : 세션에 연결된 모든 기기에서 실행 (서버 포함)
수동

 

위에서 볼 수 있듯이 액터 생성/삭제, 이동은 자동으로 Replicate 되지만 프로퍼티, RPC 함수, 컴포넌트, subobject 등은 수동으로 지정되어야 한다.

특히 다음과 같이 보통 폰이나 캐릭터의 일부인 feature 들도 replicate 되도록 지정이 필요하다:

- 메시 컴포넌트

- 머티리얼

- 애니메이션 블루프린트

- 파티클 컴포넌트

- 사운드 이미터

- 피직스 오브젝트

 

Replication Systems

: 앞서 설명했듯이 replicate 를 실행하는 내부 시스템. UE에서는 아래 3가지 시스템을 제공한다. 구체적인 게임 제작에 앞서 게임에 맞는 시스템을 선택하는 것이 좋다.

1. Generic Replication System

: 액터 레플리케이션, RPC 등을 지원하는 디폴트 시스템으로 아래와 같은 주요 특징을 가진다.

- Dormancy : Connection의 replicated 액터 리스트에 액터를 추가/제외

- Priority : 대역폭이 제한된 경우 각 프레임에 replicate 할 액터의 중요도 지정

- Relevancy : 특정 connection 에 해당 액터가 관련 있는지 없는지 지정

2. Replication Graph

: 많은 수의 replicated 액터를 수용하기 위해 디자인된 시스템 플러그인. 여기 참고

3. Iris Replication System

: 가장 최근에 추가된 시스템으로 Generic Replication System 과 나란히 작동하여 기존 액터 리플리케이션과 RPC 를 지원하는 동시에 다른 기능들을 개선하고자 디자인 됨. 도큐멘테이션 / Generic 에서 Iris 로 옮기기

 

주요 특징

- Filtering : 액터가 replicate 되는 타겟 connection 지정, replication 그룹 지정, 다이나믹 replication 필터링 제어

- Prioritization : 각 프레임에 replicate 할 액터의 중요도 지정 - 커스텀, 다이나믹 값으로 지정 가능

 

네트워크 활용 시 참고/주의

1. RPC 와 블루프린트 함수의 replicate 는 최소화할 것. ReplicatedUsing (= RepNotify) 프로퍼티로 대체할 것.

2. Multicast 함수는 선택적으로만 사용할 것.

3. 서버 내부에서만 작동할 것이 확실한 서버 전용 로직은 RPC에 포함하지 않기.

4. "Reliable" RPC 를 사용자 입력에 바인딩하는 경우, 사용자가 빠르게 반복적으로 입력하는 경우 Reliable RPC 의 대기열을 오버플로우시킬 수 있으므로, 사용자 입력 기반 활성화되는 RPC 수의 제한을 준다던가 하는 메커니즘 필요.

5. RPC 가 Tick 내에 위치하는 등 특별히 자주 호출되는 경우 Unreliable 지정

6. 함수 재활용 최대화. 예) 게임플레이 로직에 반응하여 호출된다던가, RepNotify 로 호출된다던가.

7. 액터의 네트워크 역할 확인할 것. (무슨 말이지?) 서버와 클라이언트 모두에서 활성화되는 함수의 필터링에 유용함.

8. 폰의 IsLocallyControlled 확인할 것. 폰이 owning 클라이언트와 엮여 있는지를 기반으로 필터링 시 유용.

9. 네트워크 Dormancy 활용할 것. 이것이 네트워크 게임플레이에서 가장 중요한 최적화 기능이다.

 

 

---------

공부를 계속하여 액터 레플리케이션 플로우, 프로퍼티 레플리케이션 방식, 객체 레플리케이션 순서, 최적화 방식 등에 대해 더 자세히 알아야 할 필요가 있겠다는 생각이 든다.