리플리케이션 그래프

리플리케이션 그래프 기능과 리플리케이션 그래프 노드 개요입니다.

Choose your operating system:

Windows

macOS

Linux

목차

Replication Graph (리플리케이션 그래프) 플러그인은 다수의 플레이어와 리플리케이트되는액터에도 잘 확장되도록 설계된 멀티플레이어 게임용 네트워크 리플리케이션 시스템입니다. 예로 에픽게임즈의 포트나이트 배틀 로얄은 게임마다 플레이어 100 명으로 시작하며 리플리케이트되는 액터 수는 약 5만 개입니다. 표준 네트워크 리플리케이션 전략은, 리플리케이트되는 액터 각각이 연결된 클라이언트 각각에 업데이트를 전송할지 말지 결정해야 하는데, 이런 경우 퍼포먼스가 저하지만어 서버 CPU 병목현상이 발생합니다. 액터에 문제가 있는 그룹을 파고 들거나, 단순히 업데이트 빈도를 줄이는 솔루션으로 문제가 경감될 수는 있지만, 업데이트 빈도를 줄인다는 것은 클라이언트 경험이 저하지만기도 합니다. 리플리케이션 그래프는 액터가 연결된 클라이언트 각각에 대해 평가할 필요를 없애, 클라이언트 경험 희생 없이 CPU 퍼포먼스 문제를 해결할 수 있습니다.

구조

리플리케이션 그래프에 있는 리플리케이션 그래프 노드 시리즈가 요청 시 각 클라이언트에 리플리케이트할 액터 목록을 만듭니다. 이 시스템은 단지 리플리케이트되는 액터 자체가 처리하는 함수 호출만 하는 것이 아니라 지속 오브젝트에서 만드는 것이므로, 데이터를 여러 프레임에 걸쳐 저장하고 클라이언트 사이에 공유할 수 있습니다. 이 지속 공유 데이터가 리플리케이션 그래프 시스템이 각 클라이언트에 대한 리플리케이션 목록을 만드는 데 걸리는 시간을 줄여줍니다.

리플리케이션 그래프 노드(줄여서 "노드")는 업데이트가 필요할 수도 있는 액터들을 설정하고, 그룹으로 정렬한 뒤, 클라이언트에 전송할 미리계산 목록을 저장하는 등의 실제 작업을 합니다. 궁극적인 작업은 요청 시 액터의 "리플리케이션 목록"을 연결된 각 클라이언트에 최대한 빠르게 제공하여, 서버가 클라이언트 당, 액터 당 소모하는 CPU 사이클 수를 최소로 줄이는 것입니다. 각 노드는 고유한 방식으로 작동 할 수 있으며, 개발자는 필요에 따라 자체 게임용 사용자 정의 노드를 작성하는 것이 좋습니다. 노드는 게임에 무관하거나, 게임 별 정보를 활용할 수 있습니다. 액터를 게임 내 역할에 따라 여러 노드에 배치하면 리플리케이트되는 방법과 시기를 효과적으로 제어할 수 있습니다. 새로운 노드를 만들고 리플리케이션 그래프를 사용하여 게임에서의 행동 방식에 따라 가능한 최상의 노드에 액터를 할당하면 네트워크 리플리케이션 목록을 준비하는 데 소요되는 서버 CPU 시간이 크게 감소합니다.

시스템 활성화

다음 두 가지 방법 중 하나로 사용자 정의 (리플리케이션 그래프의 상위 클래스인) Replication Driver (리플리케이션 드라이버)를 사용하도록 프로젝트를 환경설정할 수 있습니다.

  • "DefaultEngine.ini" 파일에 Replication Driver 클래스를 지정합니다.

  • 기본 Replication Driver 의 생성 Delegate 에 Replication Driver 클래스의 인스턴스를 반환하는 함수를 바인딩합니다.

ShooterGame 프로젝트는 리플리케이션 그래프를 구성하고 구현하는 좋은 예입니다. 하지만 현재 리플리케이션 그래프는 분할 화면 게임에서 작동하지 않으므로 콘솔 빌드에서는 비활성화되어 있습니다.

환경설정 (.ini) 파일

Engine 의 기본 Replication Driver 를 환경설정하려면, 프로젝트의 "DefaultEngine.ini" 파일을 엽니다. [/Script/OnlineSubsystemUtils.IpNetDriver] 섹션을 찾아 (또는 추가하고) "ReplicationDriverClassName" 항목을 설정(또는 추가)하여 사용하고자 하는 Replication Driver (또는 Replication Graph) 클래스 이름을 지정합니다. 대략 다음과 같아 보이는데, "ProjectName" 에 프로젝트 이름, "ClassName" 에 사용자 정의 클래스 이름을 넣으면 됩니다.

[/Script/OnlineSubsystemUtils.IpNetDriver]
ReplicationDriverClassName="/Script/ProjectName.ClassName"

코드로 바인딩

포르젝트에 네트워크 요구 사항이 크게 다른 여러 게임 모드와 맵이 있는 경우, Delegate (델리게이트)에 바인딩하면 현재 게임 모드 또는 맵에 적합한 Replication Driver 를 코드로 작성할 수 있습니다. 이 방법을 사용하려면, 함수를 CreateReplicationDriverDelegate 라는 UReplicationDriver 함수에 바인딩합니다. 바인딩된 함수는 원하는 Replication Driver 클래스의 유효한 인스턴스를 반환할텐데, 이런 샘플 람다 함수와 같습니다.

UReplicationDriver::CreateReplicationDriverDelegate().BindLambda([](UNetDriver* ForNetDriver, const FURL& URL, UWorld* World) -> UReplicationDriver*
{
return NewObject<UMyReplicationDriverClass>(GetTransientPackage());
});

일반적인 예제

연결된 클라이언트 수도 많고 동기화되는 액터 수는 더 많은 게임의 경우, 리플리케이션 그래프에서 유형과 상태에 따라 액터를 여러 노드에 할당하면 CPU 시간을 엄청나게 절약할 수 있습니다. 전통적인 리플리케이션 방법으로 불가능한 게임을 만들 수 있습니다. 개념적 차원에서 이런 규모의 게임은 다음과 같은 특징에 따라 리플리케이션 그래프와 리플리케이션 그래프 노드를 만들어야 그 엄청난 수의 리플리케이트되는 액터와 연결된 클라이언트를 처리할 수 있습니다.

  • 액터를 위치에 따라 그룹으로 나눕니다. 월드를 나눌 때 배틀 로얄, MOBA, MMORPG 장르 게임은 그리드 공간으로, 던전 탐험이나 통로 스타일 1인칭 3인칭 슈팅 게임은 미리 정의한 방이나 지역으로, 아니면 게임의 플레이 공간에 맞는 다른 방법으로 나눌 수 있습니다. 각 그리드 셀이나 방에 액터를 추가해 두면 거기서 보고 들을 수 있는 액터는 클라이언트 업데이트가 빨라지는데, 노드는 클라이언트의 카메라가 있는 그리드 셀이나 방에 대한 지속 액터를 클라이언트에 제공해 주기만 하면 되기 때문입니다.

  • 배치된 "휴면" 액터를 식별하여 별도의 목록에 유지합니다. 플레이어나 AI 제어 캐릭터같은 액터는 업데이트를 자주 해야겠지만, 레벨에 이미 배치되어 있는데 플레이어가 상호작용할 때까지 자체적으로 이동이나 상태 변경이 일어나지 않는 액터도 많이 있을 수 있습니다. 이러한 액터는 네트워크 업데이트 전송 없이 오랜 시간 (심지어 전체 게임 세션 동안도) 갈 수 있습니다. 예를 들어, 포트나이트 배틀 로얄에서 플레이어와 발사체는 게임에서 제거될 때까지 계속 업데이트될 것입니다. 반면 나무는, 오랫 동안 휴면 상태로 드러누워 어떤 클라이언트에도 업데이트할 필요가 없을 것입니다. 나무가 피해를 입으면, 나무를 볼 수 있는 클라이언트만 그 업데이트를 받으면 됩니다. 마지막으로 나무가 파괴된 경우, 나무의 파괴 관련 업데이트를 받은 클라이언트는 더이상 그 나무 관련 업데이트를 받을 필요가 없습니다.

  • 게임의 캐릭터가 아이템을 주워 들고 다닐 수 있다면, 그 아이템을 캐리어와 같이 업데이트합니다. 플레이어가 아이템이나 무기를 꺼내 들고 다니거나, 옷 또는 갑옷 조각을 착용하면, 그 아이템을 나타내는 (단순한 컴포넌트가 아닌 별도의 액터라 가정하고) 액터를 특수한 그룹에 넣어 소유 플레이어가 업데이트되면 항상 같이 업데이트하고, 안되면 안하는 것입니다.

  • 모든 클라이언트가 항상 아는 특수 액터 목록을 만듭니다. 모든 플레이어에게 항상 네트워크 연관성이 있는 특수 액터를 간단한 노드에 넣어 그 액터를 추적하면, 전체 목록에서 따로 떼어 유지하여 불필요한 CPU 연산 사이클 낭비를 막을 수 있습니다.

  • 특정 클라이언트에 연관성이 항상 있는 (또는 절대 없는) 특수 액터 목록을 만듭니다. 개별 액터, 또는 플레이어 팀 단위로도 비슷하게 연관성이 항상 있는 목록 노드를 만들 수 있습니다. 플레이어의 팀원은 항상 업데이트하거나, 특별한 게임 내 감지 기능으로 "발각"시킨 적을 아군 전체 팀원에게 보이게 하는 데 특히 좋습니다. "발각" 효과가 끝나면, 그 액터를 다시 기본 노드에 추가하면 됩니다.

게임 내에서 액터의 역할에 대한 지식을 기반으로 액터를 다른 노드에 지능적으로 할당하는 리플리케이션 그래프를 작성하면 서버의 CPU 시간을 최대한 활용할 수 있습니다. 그 결과 얻을 수 있는 게임의 안정적인 서버 성능은 다른 방법이었다면 현세대 하드웨어로 낼 수 없었을 것입니다. 리플리케이션 그래프 플러그인에는 대규모 온라인 게임에서 사용할 수있는 몇 가지 리플리케이션 그래프 노드 클래스가 포함되어 있습니다. 사용자 지정 노드 클래스를 작성할 때는 게임의 구체적인 내부 작동 방식을 알아두는 것이 좋습니다.

언리얼 엔진 문서의 미래를 함께 만들어주세요! 더 나은 서비스를 제공할 수 있도록 문서 사용에 대한 피드백을 주세요.
설문조사에 참여해 주세요
취소