아이리스(Iris) 는 언리얼 엔진의 기존 리플리케이션 시스템과 함께 작동하는 옵트인 리플리케이션 시스템입니다. 아이리스는 서버 인스턴스당 100명의 플레이어 수를 지원하는 포트나이트 배틀로얄 에 대한 에픽의 경험을 바탕으로 개발되었습니다. 아이리스는 다음을 갖춘 강력한 멀티플레이어 경험을 지원합니다.
- 더 넓고 인터랙티브한 월드
- 더 많은 플레이어 수
- 서버 비용 절감
현재 게임 코드에 최소한의 변경사항만 적용하면 아이리스를 사용할 수 있습니다. 아이리스를 옵트인하려면 게임 코드에서 새 엔진 API를 사용해야 합니다. 하지만 C++ 및 블루프린트의 기존 리플리케이트된 프로퍼티 와 리모트 프로시저 콜(Remote Procedure Call, RPC) 정의도 조금만 수정하면 호환됩니다. 이 문서에서는 다음 정보를 제공합니다.
개요
네트워크 게임은 리플리케이션 시스템 을 사용해 여러 컴퓨터 간에 게임 스테이트의 변경사항을 커뮤니케이션합니다. 기존에 언리얼 엔진은 다음으로 구성된 서버-클라이언트 모델을 사용합니다.
- 게임을 호스팅하는 서버 입니다. 서버 버전 게임은 권한 을 가진 것으로 간주되며, 이는 서버 게임의 인스턴스가 실질적 게임 인스턴스임을 의미합니다.
- 게임에 연결하는 플레이어 제어 클라이언트 입니다.
리플리케이션 시스템은 클라이언트에서의 게임 스테이트 변경사항이 서버로 커뮤니케이션되는 방법과 서버에 누적된 변경사항이 다시 클라이언트로 커뮤니케이션되는 방법을 제어합니다. 아이리스는 변경사항이 발생했을 때 클라이언트가 리플리케이션 시스템에 알림으로써 대부분의 작업을 수행할 것이라고 예상합니다. 따라서 아이리스는 기존 리플리케이션 시스템에 비해 여러 측면에서 퍼포먼스를 개선할 수 있습니다.
퍼포먼스 개선
아이리스는 다음 방식을 통해 리플리케이션 퍼포먼스를 개선합니다.
- 리플리케이션을 제한하는 안티패턴을 제거하여 확장성 증대
- 리플리케이션과 게임 스레드 데이터를 분리하여 동시실행 활성화
- 여러 오브젝트 및 연결에서 워크로드를 공유하여 효율성 향상
디자인
클릭하면 전체 크기로 표시됩니다. 이 다이어그램의 주요 용어가 다음 두 섹션에 정의되어 있습니다. 아이리스의 주요 컴포넌트와 주요 개념.
아이리스 리플리케이션 시스템 은 언리얼 엔진(UE) 아이리스의 주요 인터페이스입니다. 아이리스의 핵심 목표는 게임플레이 시스템과 리플리케이션 시스템 간의 종속성을 최소화하는 것입니다. 아이리스는 모든 리플리케이트된 스테이트 데이터의 완전한 사본을 양자화된 형태로 저장해 이를 달성합니다. 이를 통해 자원 소모가 많은 연산의 수를 최소화하고 연결 간에 작업을 공유할 수 있어, 더 많은 작업을 병렬로 수행하기 쉬워집니다.
아이리스의 주요 컴포넌트
리플리케이션 시스템
리플리케이션 시스템은 아이리스 내부 시스템에서 필요한 API 기능만 노출하는 인터페이스 레이어입니다. 리플리케이션 시스템은 다음 기능을 수행합니다.
- 게임에 대한 모든 네트워크 스테이트 데이터의 사본을 유지합니다.
- 연결별 리플리케이트된 액터의 스테이트를 트래킹합니다.
- 어떤 액터가 어떤 연결에 리플리케이트되는지를 필터링합니다.
- 리플리케이션의 우선순위를 설정합니다.
- 전송을 위해 데이터를 시리얼라이즈합니다.
리플리케이션 시스템 컴포넌트
다음 표에 리플리케이션 시스템의 주요 컴포넌트가 설명되어 있습니다.
| 컴포넌트 | 설명 |
|---|---|
| 리플리케이션 스테이트 | 리플리케이트되어야 하는 데이터를 포함하는 구조체입니다. 리플리케이션 시스템은 게임에 대한 모든 네트워크 스테이트 데이터의 사본을 유지합니다. |
| 우선순위 설정 | 액터와 오브젝트의 리플리케이션 우선순위를 설정합니다. |
| 필터링 | 어떤 액터가 어떤 연결에 리플리케이트될 수 있는지 필터링합니다. |
| 넷 시리얼라이저 | 네트워크 연결 상의 전송을 위해 데이터를 시리얼라이즈합니다. |
| 데이터 스트림 | 네트워크 연결 상의 데이터 리플리케이션을 구현하는 인터페이스입니다. |
리플리케이션 브리지
리플리케이션 브리지(Replication Bridge) 는 게임플레이 코드와 리플리케이션 시스템 간의 커뮤니케이션을 제어합니다. 리플리케이션 브리지의 기능은 다음과 같습니다.
- 액터 또는 오브젝트의 리플리케이션을 시작하고 종료합니다.
- 리플리케이트된 데이터의 디스크립터와 프로토콜을 빌드합니다.
- 리플리케이션 시스템에서 액터 또는 오브젝트를 추가하고 제거합니다.
주요 개념
넷 오브젝트
리플리케이트된 액터와 오브젝트는 아이리스 내부에서 넷 오브젝트로 표현됩니다. 넷 오브젝트(Net Object) 는 다음 항목으로 구성됩니다.
- 리플리케이션 프로토콜
- 리플리케이션 인스턴스 프로토콜
- 양자화된 데이터를 저장할 버퍼
리플리케이션 스테이트
리플리케이션 스테이트(Replication State) 는 리플리케이션 시스템과 게임플레이 코드 간의 스테이트 데이터를 커뮤니케이션합니다. 가장 기본적인 양식의 리플리케이션 스테이트는 리플리케이트될 데이터를 포함하는 구조체입니다. 리플리케이션 스테이트는 명시적으로 생성될 수도 있고, 기존 프로퍼티 기반 리플렉션 데이터로 빌드된 추상적 표현일 수도 있습니다.
리플리케이션 스테이트 디스크립터
리플리케이션 스테이트 디스크립터(Replication State Descriptor) 는 데이터를 리플리케이트하는 데 필요한 리플리케이션 스테이트의 모든 측면을 설명합니다. 여기에는 다음이 포함됩니다.
- 메모리 레이아웃
- 조건
- 필터링
- 우선순위 설정
- 시리얼라이제이션
모든 리플리케이션 스테이트 타입은 리플리케이션 스테이트 디스크립터를 가집니다. 동일한 타입의 리플리케이션 스테이트는 동일한 리플리케이션 스테이트 디스크립터를 사용합니다.
리플리케이션 프로토콜
리플리케이션 프로토콜(Replication Protocol) 은 내부 리플리케이션 시스템 작업에 필요한 리플리케이트된 오브젝트의 모든 측면을 설명합니다. 여기에는 리플리케이트된 오브젝트의 전체 스테이트를 구성하는 모든 리플리케이션 스테이트 디스크립터의 목록이 포함됩니다. 리플리케이션 프로토콜은 오브젝트 타입별로 다르며, 동일한 타입의 모든 인스턴스 간에 공유합니다.
리플리케이션 프래그먼트
리플리케이션 프래그먼트(Replication Fragment) 는 게임플레이 코드와 리플리케이션 시스템 사이에서 리플리케이션 스테이트를 주고받는 작업을 담당하는 아이리스 컴포넌트입니다.
리플리케이션 인스턴스 프로토콜
리플리케이션 인스턴스 프로토콜(Replication Instance Protocol) 에는 소스 오브젝트에서 데이터를 가져오고 수신한 스테이트 데이터를 수신 측의 타깃 오브젝트로 푸시 아웃하는 등의 작업을 위해 게임플레이 코드와 상호작용하는 데 필요한 데이터가 포함되어 있습니다. 리플리케이션 인스턴스 프로토콜은 리플리케이션 프래그먼트의 목록으로 표시됩니다. 리플리케이션 인스턴스 프로토콜은 인스턴스별로 다릅니다.
넷 핸들
모든 API 함수는 넷 핸들 상에서 작동합니다. 넷 핸들(Net Handle) 은 리플리케이션 시스템에서 사용하는 내부 넷 오브젝트 표현과 리플리케이트된 액터 또는 오브젝트를 연결하는 데 사용되는 고유 식별자입니다. 넷 핸들은 리플리케이션 시스템에 의해 생성되며 액터에서 BeginReplication 을 호출하면 반환됩니다.
아이리스 작업 플로
이 섹션에서는 리플리케이션을 위한 오브젝트 등록부터 시작하여 수신 측에서 새로 수신한 스테이트 데이터를 적용하는 것으로 끝나는 아이리스의 작업 플로를 설명합니다.
등록
리플리케이션을 위해 아이리스에 오브젝트를 등록하려면 게임 코드와 아이리스 측에서 모두 액션을 수행해야 합니다.
게임 코드
- 리플리케이션 시스템으로 오브젝트를 등록합니다.
- 헤더 프로퍼티를 통해 명시적 또는 암시적으로 리플리케이션 스테이트와 리플리케이션 스테이트 디스크립터를 선언합니다.
아이리스
- 오브젝트와 오브젝트의 컴포넌트에 정의된 모든 리플리케이션 스테이트를 사용하여 리플리케이션 프로토콜과 리플리케이션 인스턴스 프로토콜을 생성합니다.
- 이전에 생성된 리플리케이션 프로토콜과 리플리케이션 인스턴스 프로토콜을 사용하여 새로 등록된 오브젝트에 해당하는 넷 오브젝트를 생성합니다.
- 아이리스의 API 함수가 리플리케이트된 오브젝트와 상호작용할 수 있도록 리플리케이트된 해당 오브젝트에 고유 넷 핸들을 할당합니다.
전송자
전송 측은 두 스테이지로 구성됩니다.
전송 전 업데이트
전송 전 업데이트는 아이리스가 수신 측으로 데이터를 전송하기 위해 준비하는 여러 단계로 구성됩니다. 전송 전 업데이트에서 아이리스가 준비하는 단계는 다음과 같습니다.
- 레거시 모드로 실행 중인 경우, 스테이트 변경을 위해 리플리케이트된 모든 오브젝트를 폴링합니다.
- 적합한 넷 시리얼라이저를 사용해 모든 더티 스테이트 데이터를 양자화합니다.
- 모든 넷 오브젝트의 우선순위와 필터링 상태를 업데이트합니다.
전송 업데이트
전송 업데이트는 모든 아이리스 데이터 스트림을 티킹하여 패킷을 생성하고 채우는 것으로 구성됩니다.
넷 토큰 데이터 스트림
넷 토큰 데이터 스트림은 적합한 넷 시리얼라이저를 사용해 새 토큰을 모두 시리얼라이즈합니다.
리플리케이션 데이터 스트림
리플리케이션 데이터 스트림에서 읽은 데이터에 대해 아이리스는 다음을 수행합니다.
- 오브젝트와 스케줄링 우선순위에 따라 더티 스테이트의 오브젝트가 전송되도록 스케줄링합니다.
- 우선순위와 종속성을 기준으로 오브젝트를 정렬합니다.
- 적합한 넷 시리얼라이저를 사용해 새 데이터를 모두 시리얼라이즈합니다.
이 스테이지에서 아이리스는 데이터를 적합한 연결로 전송합니다.
수신자
수신자가 패킷 수신을 시작하자마자, 수신자는 수신한 패킷에 대해 전송자에게 알립니다. 수신한 각 패킷에 포함된 데이터는 적합한 데이터 스트림이 처리합니다.
넷 토큰 데이터 스트림
넷 토큰 데이터 스트림은 오브젝트가 더 작은 표현을 사용해 리플리케이트될 수 있도록 서버와 클라이언트 간의 오브젝트 경로를 동기화합니다.
리플리케이션 데이터 스트림
리플리케이션 데이터 스트림에서 읽은 데이터에 대해 아이리스는 다음을 수행합니다.
- 수신한 스테이트 데이터를 디시리얼라이즈하고 읽습니다.
- 리플리케이션 프로토콜을 빌드하는 데 필요하므로 새 오브젝트를 즉시 인스턴스화합니다.
- 적합한 리플리케이트된 오브젝트에 새 스테이트가 적용되고 게임플레이에 반영될 수 있도록 게임에 데이터를 푸시합니다.
프로젝트에 아이리스 사용
언리얼 엔진은 기본적으로 아이리스로 컴파일하지만, 기존 리플리케이션 시스템은 여전히 디폴트 리플리케이션 시스템으로 사용됩니다. 프로젝트에서 아이리스 사용을 활성화하려면, .uproject 파일의 Plugins 섹션에 아래의 코드 블록을 추가해서 아이리스 플러그인을 활성화해야 합니다.
{
"Name": "Iris",
"Enabled": true
},
모듈의 .Build.cs 파일에 빠르고 쉽게 아이리스의 필수 종속성을 추가하기 위해 SetupIrisSupport 를 호출합니다. 모듈에 아이리스를 포함하려면 모듈의 .Build.cs 파일에 다음 코드를 추가하세요.
SetupIrisSupport(Target);
런타임에 아이리스 활성화 또는 비활성화
명령줄 실행인자를 사용해 런타임에 아이리스를 활성화하거나 비활성화할 수 있습니다.
-UseIrisReplication=1: 아이리스 활성화-UseIrisReplication=0: 아이리스 비활성화
IrisNetDriverConfigs 엔트리에서 아이리스를 활성화한 넷 드라이버는 리플리케이션에 아이리스를 사용합니다.
아이리스로 언리얼 엔진 컴파일 비활성화
언리얼 엔진이 아이리스로 컴파일하는 것을 완전히 비활성화하려면, .Build.cs 파일에서 bUseIris = false 로 설정합니다.