본문 바로가기
Unreal Engine Practice

UnrealEngine 네트워킹,리플리케이트,리플리케이션(1)

by Srff5123 2025. 3. 5.
728x90

1. 네트워킹 개요

멀티플레이어 세션에서 게임 상태(State) 정보는 인터넷 접속을 통해 여러 컴퓨터 간에 전달된다.

싱글 플레이어 게임의 경우에는 모든 정보가 하나의 컴퓨터에 저장된다.

따라서 멀티플레이어 프로그래밍은 본질적으로 싱글 플레이어 게임 프로그래밍보다 더 복잡하다.

플레이어 간 정보 공유 프로세스는 세심한 주의를 요하며 여러 추가 단계를 거쳐야 한다.

 

프로젝트 시작부터 멀티플레이를 염두에 두고 모든 게임플레이를 빌드해야 한다.

팀에서 멀티플레이 게임을 만들기 위한 추가 단계를 일관되게 구현한다면,

싱글 플레이어 게임에 비해 게임플레이 구축에 그렇게 많은 시간이 걸리지는 않을 것이다.

장기적으로 팀이 프로젝트를 디버그하고 서비스하는 것이 전체적으로 더 쉬워질 것이다.

 

멀티 플레이용으로 프로그래밍한 모든 게임플레이는 싱글에서도 작동한다.

하지만 네트워킹 없이 이미 구축한 코드베이스를 리팩터링(Refactoring)하려면, 전체 프로젝트를 뒤져가며

거의 모든 게임플레이 함수를 다시 프로그래밍해야 한다.

그렇기에 멀티플레이 기능이 절대 필요 없는 프로젝트라는 것에 확신이 없다면 항상 멀티플레이용으로 프로그램하는 것이 좋다.

 

2. 클라이언트 - 서버 모델

싱글 플레이어 게임이나 로컬 멀티플레이어 게임에서는, 게임이 독립형 게임으로 로컬에서 실행된다.

플레이어가 단일 컴퓨터에 입력을 연결하고 해당 로컬 컴퓨터에서 액터와 월드, 각 플레이어의 유저 인터페이스 등, 게임의 모든 것을 직접 제어한다.

 

실글 플레이어와 로컬 멀티플레이어는 하나의 컴퓨터에서만 실행된다.

 

네트워크 멀티플레이 게임의 경우 언리얼 엔진은 클라이언트-서버 모델을 사용한다. 네트워크에 있는 하나의 컴퓨터가 서버가 되어 멀티플레이 게임 세션을 호스팅하고, 서버에 접속한 다른 모든 플레이어의 컴퓨터는 클라이언트가 된다.

서버는 접속된 각 클라이언트와 게임 상태 정보를 공유하고 서로 통신할 수 있는 수단을 제공한다.

 

네트워크 멀티플레이는 게임이 서버 1과 서버에 접속한 여러 클라이언트 2 사이에서 실행된다.

서버는 게임플레이를 처리하고 클라이언트는 사용자에게 게임을 보여준다.

 

게임을 호스팅하는 서버는 하나의 진정한 오소리티(Authority : 권한)있는 게임 상태를 보유한다.

즉, 서버는 멀티 플레이 게임이 실제로 벌어지는 곳이다.

클라이언트는 각각 서버에 소유한 폰(Pawn)을 원격 제어하는데, 게임 내 액선을 수행하도록 폰에 프로시저(Procedure : 절차) 호출을 전송한다.

하지만, 서버는 클라이언트 모니터에 직접 영상을 스트리밍하지 않는다. 대신, 서버는 게임 상태에 대한 정보를 각 클라이언트 "리플리케이트" 하여 존재해야 하는 액터와 그러한 액터의 행동 방식, 보유해야 하는 다양한 변수값을 알려준다.

그러면 각 클라리언트는 이 정보를 사용하여 서버에서 플레이되는 게임을 매우 비슷하게 시뮬레이션한다.

 

3. 클라이언트 - 서버 게임 플레이 예시

이 경우 실제적인 게임플레이 프로그래밍이 어떻게 달라지는지를 보여주기 위해 멀티플레이어의 게임의 두 플레이어를 예시로 들어 본다.

시스템에서 이 두 플레이어를 플레이어 1과 2로 칭하고, 서로 발사체를 발사하는 프로세스를 살펴본다.

 

1.로컬 게임플레이

우선 플레이어 1이 입력을 눌러 발사체를 날린다.

- 플레이어 1의 폰이 여기에 반응하여 발사체를 날린다.

- 플레이어 1의 발사체를 스폰하고 그에 따른 사운드와 이펙트를 재생하여준다.

 

1.네트워크 게임플레이

플레이어 1이 로컬에서 입력을 눌러 발사체를 날린다.

- 플레이어 1의 로컬 폰이 대응되는 서버의 폰에 무기 발사 명령을 전달한다.

- 서버에 있는 플레이어 1의 발사체를 스폰한다.

- 서버가 연결된 각 클라이언트에 플레이어 1의 발사체 사본을 생성하라고 지시한다.

- 서버에 있는 플레이어 1의 발사체가 각 클라이언트에 발사체와 관련된 사운드와 이펙트 재생을 전달한다.

 

 

2. 로컬 게임 플레이

플레이어 1의 발사체가 앞으로 이동한다.

 

2. 네트워크 게임플레이

서버에 있는 플레이어 1의 발사체가 앞으로 이동한다.

- 서버가 각 클라이언트에 플레이어1의 발사체가 이동하면 그 무브먼트를 리플리케이트하라고 전달하고,

그에 따라 각 클라이언트에서도 플레이어1의 발사체도 이동한다.

 

3. 로컬 게임 플레이

 

플레이어 1의 발사체가 플레이어 2의 폰과 충돌한다.

- 이 콜리전이 플레이어 1의 발사체가 소멸하는 함수를 트리거하여 플레이어 2의 폰에 데미지를 주고

그에 따른 사운드와 이펙트를 재생한다.

- 플레이어 2가 받은 데미지에 대한 반응으로 화면 이펙트를 재생한다.

 

3. 네트워크 게임플레이

서버에 있는 플레이어 1의 발사체가 플레이어 2의 폰과 충돌한다.

- 이 콜리전이 서버에 있는 플레이어 1의 발사체가 소멸하는 함수를 트리거한다.

- 서버가 자동으로 각 클라이언트에 플레이어 1의 발사체 사본을 소멸하라고 전달한다.

- 이 클리전이 모든 클라이언트에 콜리전에 따른 사운드와 비주얼 이펙트를 재생하라고 전달하는 함수를 트리거한다.

- 서버에 있는 플레이어 2의 폰이 발사체의 콜리전으로 부터 데미지를 받는다.

- 서버에 있는 플레이어 2의 폰이 플레이어 2의  클라이언트에 받은 데미지에 대한 반응으로 화면 이펙트를 재생하라고 전달한다.

 

 

독립형 게임에서는 이러한 상호작용이 모두 같은 컴퓨터의 같은 월드에서 벌어지므로 문자 그대로 이해하기도 쉽고 프로그래밍하기도 쉽다. 예를 들어, 오브젝트 스폰 시, 모든 플레이어가 그 장면을 볼 수 있다는 것을 당연하게 받아들일 수 있다.

 

네트워크 게임에서는 이러한 상호작용이 서버에 존재하는 월드, 플레이어 1의 클라이언트에 존재하는 월드, 플레이어 2의 클라이언트에 존재하는 월드, 그리고 세션에 참여하는 각 클라이언트의 추가 월드 등, 여러 개의 서로 다른 월드에서 벌어진다. 

서로 다른 컴퓨터의 각 월드에 각각의 폰과 폰의 무기, 폰이 발사하는 발사체의 사본이 있다.

게임이 실제 플레이 되는 곳은 서버이지만, 클라이언트의 월드에서 똑같은 이벤트가 발생하는 것처럼 보이게 해야 한다.

따라서, 각 클라이언트에 선별적으로 정보를 전송하여 서버에 있는 월드의 시각적 표현을 생성해야 한다.

 

이 프로세스에서는 필수 게임플레이 상호작용(콜리전, 무브먼트, 데미지), 이펙트(비주얼 이펙트, 사운드) 및

개인 플레이어 정보(HUD 업데이트)를 구분한다.

이러한 각 요소는 특정 컴퓨터나 네트워크에 있는 컴퓨터 집합과 관련된다.

하지만, 이 정보를 리플리케이트하는 프로세스는 완전히 자동이 아니므로, 게임플레이를 프로그래밍하면서 어떤 정보를

어떤 컴퓨터에 리플리케이트할지 지정해야 한다.

주요 과제는 어떤 정보를 리플리케이트해야 할지, 그리고 모든 플레이어에게 일관된 경험을 제공하는 동시에

리플리케이트하는 정보량을 최소화하여 가능한 한 네트워크 대역폭을 적게 사용하도록 하기 위해 어떻게 할지를 선택하는 것이다.

 

4. 네트워크 모드 및 서버 타입

네트워크 모드(Network mode)는 네트워크 멀티플레이어 세션과 컴퓨터의 관계를 설명한다.

게임 인스턴스는 다음 네트워크 모드 중 하나를 취할 수 있다.

 

1. 독립형(Standalone)

게임이 원격 클라이언트 접속을 허용하지 않는 서버로 실행된다.

게임에 참여하는 모든 플레이어는 로컬 플레이어뿐이다.

이 모드는 싱글 플레이어 및 로컬 멀티플레이 게임에 사용된다.

서버 측 로직과 클라이언트 측 로직 모두를 로컬 플레이어에 맞게 실행한다.

 

2. 클라이언트(Client)

게임이 네트워크 멀티플레이어 세션으로 서버에 접속된 클라이언트로 실행된다.

어떠한 서버 측 로직도 실행하지 않는다.

 

3. 리슨 서버(Listen Server)

게임이 네트워크 멀티플레이어 세션을 호스팅하는 서버로 실행된다.

원격 클라이언트의 접속을 허용하며, 서버에 바로 로컬 플레이어가 있다.

이 모드는 가벼운 협동 및 경쟁 멀티플레이어에 자주 사용된다.

 

4. 데디케이티드 서버(Dedicated Server)

게임이 네트워크 멀티플레이어 세션을 호스팅하는 서버로 실행된다.

원격 클라이언트의 접속을 허용하지만, 로컬 플레이어는 없다.

따라서, 더 효율적인 운영을 위해 그래픽, 사운드, 입력 및 기타 플레이어 중심 기능을 버린다.

이 모드는 높은 지속성이나 보안, 대규모 멀티플레이어가 필요한 게임에 자주 사용된다.

 

 

리슨 서버는 게임 사본이 있는 어떤 사용자라도 리슨 서버를 시작하고 같은 컴퓨터에서 플레이할 수 있기에

사용자가 자발적으로 쉽게 구성할 수 있다.

리슨 서버를 지원하는 게임은 서버를 시작하거나 참여할 서버를 검색하기 위한 게임 내 UI를 제공하는 경우가 많다.

하지만, 리슨 서버를 호스팅하는 플레이어가 서버에서 직접 플레이하기 때문에 네트워크 접속을 통해 플레이해야 하는

다른 플레이어보다 유리하므로 공정성과 부정행위 문제가 대두된다.

또한, 서버로 실행하면서 그래픽과 사운드 같은 플레이어 관련 시스템을 지원해야 하기에 추가 부하가 발생한다.

이러한 요인 때문에 경쟁이 치열한 환경 게임이나 게임에 관련된 네트워크 부하가 매우 높은 게임에는 적합하지 않다.

하지만, 소규모 플레이어 그룹이 즐기는 가벼운 협동 및 경쟁 멀티플레이어용으로는 매우 편리하다.

 

데디케이티드 서버는 더 비싸고 환경설정이 어려우며, 게임에 참여하는 모든 플레이어가 별도의 컴퓨터에서 자체적으로

네트워크에 접속해야 한다.

하지만 데이케이티드 서버에 참여하는 모든 플레이어가 같은 타입의 접속을 통해 게임을 경험하므로 공정성이 보장된다

데디케이티드 서버는 그래픽을 렌더링하지도 않고 기타 로컬 플레이어에만 관련된 다른 로직을 수행하지도 않으므로,

게임 플레이와 네트워킹을 더 효율적으로 처리할 수 있다.

따라서 보안이나 공정성, 안정성 때문에 신뢰할 수 있는 서버가 필요하거나 고성능이 필요한 게임, 많은 수의 플레이어가 필요한 게임용으로 데디케이티드 서버가 선호된다.

이러한 게임에는 MMO, 경쟁적인 MOBA, 빠르게 진행되는 온라인 슈팅 게임 등이 있다.

 

 

5. 액터 리플리케이션

리플리케이션은 네트워크 세션에 있는 다양한 컴퓨터 간에 게임 동작 정보를 재현하는 프로세스이다.

리플리케이션이 올바르게 설정되면, 다른 컴퓨터의 게임 인스턴스가 동기화 된다.

기본적으로 대부분의 액터는 리플리케이션이 활성화되어 있지 않으며, 로컬에서 모든 함수를 수행한다.

C++ 액터 클래스에서 bReplicates 변수를 설정하거나 액터 블루프린트의 리플리케이트(Replicates) 세팅을 true로 설정하여 특정 클래스의 액터에 대한 리플리케이션을 활성화할 수 있다.

 

다음은 네트워크 게임플레이 제작에 많이 사용하는 기능들이다.

 

1. 생성 및 소멸(Creation and Destuction)

서버에서 오소리티(Authority) 있는 버전의 액터가 스폰되면 접속된 모든 클라이언트에 자동으로 원격 프록시(proxy : 대리권)가 생성된다. 그런 다음, 정보가 그러한 원격 프록시에 리플리케이트된다. 오소리티 있는 액터를 소멸시키면 접속된 

모든 클라이언트에 있는 원격 프록시가 자동으로 소멸된다.

 

2. 무브먼트 리플리케이션(Movement Replication)

오소리티 있는 액터에 대해 리플리케이트 무브먼트(Replicate Movement)가 활성화되어 있거나 C++에서

bReplicateMovement가 true로 설정되어 있으면, 자동으로 위치(Location)와 회전(Rotation), 속도(Velocity)가 

리플리케이트 된다.

 

3. 변수 리플리케이션(Variable Replication)

리플리케이티드 변수로 지정된 변수는 값이 변경될 때마다 오소리티 있는 액터에서 원격 프록시로 자동으로 리플리케이트된다.

 

4. 컴포넌트 리플리케이션(Component Relication)

액터 컴포넌트가 액터 컴포넌트를 소유한 액터의 일부로 리플리케이트된다.리플리케이트되는 것으로 지정된 컴포넌트 내 모든 변수가 리플리케이트되며, 컴포넌트 내에서 호출된 모든 RPC(Remote Procedure Call : 원격 프로시저, 원격지의 프로세스에 접근하여 프로시저나 함수를 호출하는 기술로, 프로세스 간 통신의 한 방법) 호가 액터 클래스에서 호출된 RPC와 일관되게 행동한다.

 

5. 원격 프로시저 호출(RPC)

RPC는 네트워크 게임에서 특정 컴퓨터로 전송되는 특별 함수이다.처음 RPC를 호출한 컴퓨터가 무엇이든 지정된 컴퓨터에서만 RPC 구현이 실행된다.서버나 클라이언트(액터 소유 클라이언트 서버에서만 실행) 또는 NetMulticast(서버를 포함, 세션에 접속된 모든 컴퓨터에서 실행)로 지정할 수 있다.

 

생성 및 소멸, 무브먼트 같은 일반적인 사용 사례는 자동으로 처리되지만, 리플리케이션을 활성화해도다른 모든 게임플레이 피처(Feature)는 기본적으로 자동으로 리플리케이트되지 않는다.게임에 적합하도록 리플리케이트하려는 변수와 함수를 정확하게 지정해야 한다.

 

리플리케이트 되지 않는 액터와 폰, 캐릭터1. 스켈레탈 메시(Skeleteal Mesh), 스태틱 메시(Static Mesh) 컴포넌트2. 머테리얼(Material)3. 애니메이션 블루프린트(Animation Blueprints)4. 파티클 시스템(Particle Systems)5. 사운드 이미터(Sound Emitters)6. 피직스 오브젝트(Physics Objects)

 

이러한 각 요소는 모든 클라이언트에서 개별적으로 실행된다.하지만, 이러한 시각적 요소를 구동하는 변수가 리플리케이트되면, 모든 클라이언트가 같은 정보를 보유하게 되어거의 같은 방식으로 해당 요소가 시뮬레이션 된다.

 

6. 네트워크 역할 및 오소리티

액터의 네트워크 역할은 네트워크 게임 중 액터를 제어할 컴퓨터는 결정한다.오소리티 있는 액터는 액터의 스테이트(동작)을 제어하는 것으로 간주되며, 정보를 네트워크 멀티플레이 세션 내에 있는 다른 컴퓨터로 리플리케이트한다.원격 프록시는 원격 컴퓨터에 있는 해당 액터의 사본으로, 오소리티 있는 액터로부터 리플리케이트된 정보를 수신한다.이는 로컬 역할(Local Role)과 원격 역할(Remote Role) 변수로 추적되며, 이러한 변수는 다음 값을 취할 수 있다.

 

1. None(없음)

액터가 네트워크 게임에서 역할이 없으며 리플리케이트하지 않는다.

 

2. Authority(오소리티)

액터가 오소리티 있는 액터이며, 다른 컴퓨터에 있는 액터의 원격 프록시로 정보를 리플리케이트 한다.

 

3. Simulated Proxy(시뮬레이션 프록시)

액터가 다른 컴퓨터의 오소리티 있는 액터에 의해 완전히 제어되는 원격 프록시 이다.픽업이나 발사체, 인터랙치브 오브젝트 같은 대부분의 네트워크 게임 액터는 원격 클라이언트에서시뮬레이션된 프록시로 나타난다.

 

4. Autonomous proxy(자율 프록시)

액터가 일부 함수를 로컬에서 수행할 수 있지만, 오소리티 있는 액터로부터 보정을 수신하는 원격 프록시이다.자율 프록시는 액터로부터 보정을 수신하는 원격 프록시이다.자율 프록시는 보통 폰처럼 플레이어가 직접 제어하는 액터로 예약된다.

 

언리얼 엔진에서 사용하는 기본 모델은 서버-오소리티(Server-Autoritative)모델로, 이는 해당 서버가 항상게임 스테이트에 대한 오소리티를 보유하며, 정보가 항상 서버에서 클라이언트로 리플리케이트 된다는 뜻이다.서버의 액터가 오소리티의 로컬 역할을 보유할 것으로 예상하며,원격 클라이언트의 대응 액터가 시뮬레이션된 프록시 또는 자율 프록시의 로컬 역할을 보유할 것으로 예상한다.

 

 

 

 

 

 

 

728x90