[Unreal]언리얼 엔진 멀티 플레이어 시스템 Part1

Doorbals·2023년 8월 15일
2

Unreal Multi Player

목록 보기
1/2

언리얼 엔진 멀티 플레이어 시스템

  • 언리얼 엔진에는 멀티 플레이어 게임을 위한 네트워킹 시스템이 제공된다.
  • 멀티 플레이어 게임은 동일한 게임의 여러 인스턴스가 동시에 실행되는 것을 목표로 한다.
  • 즉, 아래의 예시들이 여러 인스턴스에 해당된다.
    • 1) 동일한 시스템의 다른 프로세스
    • 2) 동일한 로컬 네트워크의 다른 컴퓨터
    • 3) 인터넷을 통해 서로 다른 위치에 존재하는 플레이어
  • 이처럼 다양한 게임 인스턴스는 서로 소통함으로써 공유하는 세계를 일관되게 구축해야 한다.

  • 언리얼 엔진의 네트워크 모델에서 플레이어(Client)는 서버에 연결 상태를 유지하고, 서버는 월드를 신뢰할 수 있는 상태(Reliable)로 유지한다.
  • 서버에서 변경 사항이 발생하면 해당 변경 사항은 리플리케이션(Replication)이라는 프로세스의 일부로 필요에 따라 클라이언트로 전파된다.
    • 리플리케이션 시스템은 게임 코드와 통합되어 멀티 플레이어 게임을 쉽게 개발하도록 해준다.
    • 통신을 위해 소켓을 따로 열거나 패킷을 보내지 않아도 되며, 데이터 직렬화(Serealization) / 인코딩(Encoding) / 바이트 순서 / 타임스탬프 / 재정렬 및 라우팅(Routing) 등을 처리하지 않고, 단순히 해당 프로퍼티를 복제하기를 요구하면 복제되는 시스템이다.

Net Mode

  • World의 속성으로 네 가지의 모드(Standalone / DedicatedServer / ListenServer / Client)가 존재하며, 아래의 3가지 질문을 통해 모드를 나눌 수 있다.

1. Playable?

  • 게임을 플레이 할 수 있는가?
  • GameInstance에 LocalPlayer가 존재하고, 해당 플레이어의 입력을 처리하고, 월드를 뷰포트로 렌더링하고 있는가?

2. Authority?

  • 우리는 서버인가?
  • GameInstance에 GameMode 액터가 포함된 World의 정식 사본이 있는가?

3. Open To Clients?

  • (우리가 서버라면) 원격 연결 시도를 위해 열려있는가?
  • 다른 플레이어가 클라이언트로 참여해 게임을 플레이 할 수 있는가?

  • 게임을 시작하면 프로세스의 수명동안 유지되는 GameInstance 개체를 얻은 다음, 게임에서 URL(서버 주소 또는 맵 이름)을 탐색한다.
  • 이후 게임이 맵을 로드하게 되고, 맵은 World를 제공하며, 이 World의 Net Mode는 GameInstance가 시작된 방식에 따라 달라진다.

4가지 Net Mode의 차이점

1. Standalone

  • 게임 인스턴스가 로컬로 맵을 로드한 경우, World의 Net Mode는 Standalone이 된다.
  • 단일 게임 인스턴스는 서버이자 클라이언트이지만, 단일 플레이어 구성에서 실행되기 때문에 다른 클라이언트가 연결할 수 없다.

2. Dedicated Server

  • 로컬 플레이어와 뷰포트가 없는 게임 인스턴스
  • 사운드, 그래픽, 사용자 입력 등 플레이어 관련 기능을 제거하여 효율적인 실행 가능한 서버
  • 플레이어가 클라이언트로 연결할 수 있는 서버 전용 콘솔 응용 프로그램으로서 작동한다.

3. Listen Server

  • 맵을 로컬로 로드하지만 Listen 옵션을 추가하면 Listen Server로 실행된다.
  • 기본적으로 Standalone과 동일하지만 게임의 다른 인스턴스들이 클라이언트로 연결할 수 있다.

4. Client

  • 게임 인스턴스가 원격 서버로 연결된 경우, 해당 World는 Client 모드를 갖는다.
  • 이 때 게임은 로컬 플레이어가 플레이 할 수 있지만, 서버 요청에 따라 World가 업데이트 된다.
  • 서버가 아닌 유일한 모드로, 서버 측의 로직이 실행되지 않는다.

언리얼 엔진의 네트워킹 시나리오

1. Single Player

  • 하나의 게임 인스턴스가 있고, 해당 World는 Standalone 모드에서 실행된다.

2. Multi Player

  • 각각 고유한 게임 인스턴스들이 있고, 고유한 World 복사본이 있는 여러 프로세스가 있다.
  • 이러한 프로세스 중 하나는 Listen Server 또는 Dedicated Server가 된다.

Replication 시스템 개요

  • 멀티 플레이어 게임이 실행되면 언리얼 엔진의 Replication 시스템이 동작하여 게임의 다양한 인스턴스가 모두 동기화되도록 한다.
  • 각 인스턴스는 공유되는 World에 대해 자체적으로 복사본을 만들고, Replication 시스템은 이것이 정확하게 동작하는지 확인한다.
  • 이러한 역할 수행을 위해 Replication 시스템은 NetDriver, NetConnection, Channel 라는 클래스들에 의존한다.

  • 서버를 부팅하면 NetDriver가 생성되고, 원격 프로세스로부터의 메시지 수신이 시작된다.
  • 클라이언트를 부팅하면 자체 NetDriver가 생성되어 서버에 연결 요청을 보낸다.
  • 서버와 클라이언트의 NetDriver가 연결되면 각 NetDriver 내에서 NetConnection이 설정된다.
    • 서버에는 연결된 각 원격 플레이어에 대해 하나의 NetConnection이 존재한다.
    • 각 클라이언트에는 서버에 대한 연결을 나타내는 단일 NetConnection이 존재한다.

  • 모든 NetConnection에는 다양한 채널이 존재한다.
  • 일반적으로 NetConnection에는 ControlChannel, VoiceChannel이 있고, 각 NetConnection에는 현재 해당 NetConnection을 통해 복제되고 있는 각 액터들에 대한 ActorChannel들이 있다.
    • 이를 통해 Replicate는 Actor 수준에서 발생한다는 것을 알 수 있다.

  • 네트워크를 통해 동기화를 유지하기 위해 액터가 필요한 경우, 해당 액터를 Replication 가능하도록 설정한다.
  • Replicate 가능한 액터가 특정 플레이어와 관련된 것이면 서버는 해당 플레이어의 NetConnection에서 ActorChannel을 만들고, 서버와 클라이언트는 해당 채널을 사용하여 해당 액터에 대한 정보를 교환한다.

Actor Replication

  • 액터가 Replicate 될 때, 세 가지의 결과가 발생한다.

1) LifeTime

  • 액터의 수명이 서버와 클라이언트 간에 동기화되어 유지된다.
  • 서버가 Replicate 설정된 액터를 생성하면 클라이언트에 알림이 전달되어 자체적인 복사본을 생성한다.
  • 액터가 서버에서 소멸되면 클라이언트에서도 자동으로 소멸된다.

2) Property Replication

  • 액터에 Replicate 플래그가 지정된 속성이 있는 경우, 해당 속성이 서버에서 변경되면 새 값이 클라이언트에 전달된다.

3) RPCs(Remote Procedure Call)

  • RPC에는 3가지 종류가 있다.
    • Client : 서버에서 호출되지만 클라이언트에서 실행되는 RPC
      • 해당 액터를 실제 소유하고 있는 클라이언트에서만 함수 실행
    • Server : 클라이언트에서 호출되지만 서버에서 실행되는 RPC
      • 클라이언트는 RPC가 호출되는 액터를 소유해야 한다.
    • Multicast : 서버에서 호출된 후 서버를 포함하여 연결된 모든 클라이언트에서 실행되는 RPC
      • 클라이언트에서 호출될 경우, 로컬에서만 실행되고 서버에서는 실행 X
  • RPC를 사용하여 서버와 클라이언트 간에 메시지를 주고 받을 수 있다.
  • 실행될 때만 Replicate 된다.

Ownership (소유권)

  • 모든 액터는 소유자로 지정된 다른 액터를 가질 수 있다.
  • 일반적으로 액터 생성 시 소유자를 설정하지만, 런타임에 SetOwner를 호출할 수도 있다.
  • NetConnection은 플레이어를 나타내며, 플레이어가 게임에 로그인되면 이와 연결된 PlayerController 액터를 소유한다. 이 경우 NetConnection은 다시 PlayerController로 추적할 수 있는 모든 액터를 소유한다.
  • 아래와 같은 경우, Weapon 액터로부터 시작해 PlayerController에 대한 소유자 참조 체인을 따라가면서 해당 Weapon 액터가 특정 클라이언트 연결에 속해 있는지 알 수 있다.

Enabling Actor Replication

  • 액터가 Replicate 되려면 bReplicates 플래그가 활성화 되어야 한다.
  • 런타임에 Replicate를 켜거나 끌 수도 있다.
  • 서버는 해당 액터를 해당 클라이언트에 Replicate 하기 위해 지정된 NetConnection 내에서 ActorChannel을 열 수 있다.

Relevancy (관련성)

  • 액터의 관련성에 따라 어떤 연결이 언제 발생할지 결정된다.
  • 액터가 Replicate 가능할 때, 서버의 NetDriver는 각 클라이언트 연결에 대해 해당 액터를 확인해 해당 액터가 해당 클라이언트와 관련 있는지 확인한다.
  • 일부 액터는 Replicate가 가능한 한, 서버가 이를 항상 모든 클라이언트에 복제한다. (bAlwaysRelevant = true)
    • 예를 들면, GameState 및 PlayerState는 항상 모든 클라이언트와 관련이 있다.
  • 소유권은 관련성에 있어 중요한 역할을 한다. 특정 플레이어가 소유하거나 특정 행동을 지시하는 액터는 항상 해당 클라이언트와 관련된 것으로 간주한다. 일부 액터(ex. PlayerController)는 소유자에게만 관련되도록 구성되어 있으므로 소유하지 않은 클라이언트에는 복제되지 않는다.
  • 소유자로부터 관련성을 상속하도록 액터를 구성할 수도 있다.
  • 위와 같은 특수 플래그 중 어느 것도 설정되지 않고, 어떤 클라이언트도 액터를 소유하지 않은 경우도 있다.
    • 해당 경우에는 액터가 숨겨져 있고, 충돌이 비활성화 되어있으면 관련성이 없는 것으로 간주된다.
    • 그렇지 않은 경우 관련성은 클라이언트 연결에 해당하는 플레이어와의 거리를 기반으로 한다. 액터에서 플레이어까지의 제곱 거리가 NetCullDistanceSquared보다 작으면 액터는 해당 플레이어와 관련이 있다.

Update Frequency & Priority (업데이트 빈도 및 우선순위)

  • 액터가 Replicate 되면 업데이트 빈도 및 우선순위에 따라 서버가 해당 액터와 관련된 클라이언트에 업데이트를 보내는 빈도가 결정된다.
  • NetUpdateFrequency를 설정할 경우, 액터를 확인하여 변경사항이 있을 경우 잠재적으로 클라이언트에 새 데이터를 보내는 초당 횟수가 결정된다.
  • 서버의 NetDriver는 대역폭 포화를 완화하기 위해 몇 가지 간단한 로드 밸런싱을 사용한다. NetDriver가 작업할 수 있는 대역폭은 한정되어 있으므로, 우선순위에 따라 관련 액터를 정렬한 뒤, 사용 가능한 대역폭을 모두 사용할 때까지 네트워크 업데이트를 실행한다.
    • 플레이어에 더 가까운 액터는 더 높은 우선순위로 가중치가 부여되고, 한동안 업데이트 되지 않은 액터에도 더 높은 우선순위가 부여되므로 모든 액터는 결국 언젠가는 우선순위에 따라 작업된다.
  • 액터의 NetPriority 속성을 설정하면 추가적인 가중치를 부여할 수 있다.
    • 예를 들면, NetPriority를 5.0으로 설정할 경우 그렇지 않은 경우보다 5배 더 자주 업데이트 되어야 한다고 지시하는 것이다.

👁️‍🗨️ 출처

profile
게임 클라이언트 개발자 지망생의 TIL

4개의 댓글

comment-user-thumbnail
2023년 8월 15일

좋은 글 감사합니다.

1개의 답글
comment-user-thumbnail
2023년 12월 11일

좋은 글 감사합니다.
덕분에 공부하는데 굉장히 큰 도움이 되고 있습니다.

답글 달기
comment-user-thumbnail
2024년 1월 18일

좋은 글 감사합니다!

답글 달기