This document is about: QUANTUM 2
SWITCH TO

Quantum 소개

개요

Photon Quantum은 유니티로 만들어진 온라인 멀티플레이어용 고성능 결정론적 ECS(Entity Component System)입니다.

Photon Quantum은 액션 RPG, 스포츠 게임, 전투 게임등과 같은 지연에 민감한 온라인 게임에 이상적인 예측/롤백 접근법을 기반으로 합니다.

또한 Quantum은 개발자가 뷰/프레젠테이션(Unity)에서 시뮬레이션 로직(quantum ECS)을 완전히 분리하는 동시에 네트워크 구현 세부 사항(내부 예측/롤백 + 전송 계층 + 게임 애그노스틱 서버 로직)을 처리할 수 있도록 지원합니다.

Quantum Decoupled Architecture
Quantum 엔진-아키텍처 개요. 게임 플레이 코드는 완전히 프리젠테이션 로직과 디커플되어있습니다.

Quantum 은 다음으로 이루어진 최신 기술을 구현합니다:

  • 서버에서 관리되는 예측/롤백 시뮬레이션 코어.
  • 스파스 셋 ECS 메모리 모델과 API (SDK 버전 2에서 도입).
  • 스테이스리스 결정론적 라이브러리의 완전한 집합(math, 2D 그리고 물리, 네비게이션 등).
  • 리치 유니티 편집기 통합 및 툴링.

이 모든 기능은 성숙하고 업계에서 입증된 기존 Photon 제품 및 인프라(photon 실시간 전송 계층, 호스트 서버 로직용 Photon 서버 플러그인 등) 기반으로 구축되었습니다.

락스텝이 없는 결정론

결정론적 시스템에서 게임 클라이언트는 모든 클라이언트에서 로컬로 실행되는 시뮬레이션과 플레이어 입력만 교환합니다. 과거에는 게임 클라이언트가 시뮬레이션의 각 틱/프레임을 업데이트하기 전에 다른 플레이어의 입력을 기다리는 락스텝 접근 방식을 사용했습니다.

그러나 Quantum에서는 게임 클라이언트가 입력 예측을 사용하여 로컬로 시뮬레이션을 진행할 수 있으며, 고급 롤백 시스템은 게임 상태를 복원하고 잘못된 예측을 다시 시뮬레이션하는 작업을 처리합니다.

또한 Quantum은 입력 지연과 클럭 동기화를 관리하기 위해 게임-상호운용 권한 집중 서버 컴포넌트(Photon 서버 플러그인)에 의존하기 때문에, 클라이언트는 절대로 시뮬에시연 포워드 롤백/호가인을 위하 가장 낮은 것을 대기할 필요가 전혀 없습니다:

Quantum Server-Managed predict/Rollback
Quantum 에서는 결정론적 입력 교환은 게임-상호운용 서버 로직에 의해 관리됩니다. 이를 통해 플레이어들은 좋은 환경의 네트워크에서 방해되는 나쁜 네트워크의 경험을 없애줍니다.

다음은 Quantum 게임의 빌딩 블록의 기본사항입니다:

  • Quantum 서버 플러그인: 게임 클라이언트 간의 입력시간과 전송을 관리하며, 클럭 동기화 소스의 기능을 수행합니다. 고객이 호스트 한 백엔드 시스템(매치메이킹, 플레이어 서비스 등)과 통합하기 위해 확장할 수 있습니다.
  • 게임 클라이언트 시뮬레이터: Quantum 서버와 통신하고, 로컬 시뮬레이션을 수행하며 모든 입력 예측과 롤백을 수행합니다.
  • 사용자 정의 게임플레이 코드: Quantum ECS 를 이용하여 독립된 순수 C# 시뮬레이션(유니티로부터 분리)으로서 고객이 개발하였습니다.
    Quantum의 API는 고성능 코드를 구성하는 방법에 대한 프레임워크를 제공하는 것 외에도 결정론적인 3D 벡터 연산, 2D 및 3D 물리학 엔진, navmesh pathfinder 등 모든 게임에서 재사용할 수 있는 사전 빌드된 구성요소(데이터)와 시스템(로직)을 다양하게 제공합니다.

올드 스쿨 코딩

모든 시뮬레이션 코드는 출시할 때 고성능이어야 한다는 가정부터 시작하여 Quantum 내부 시스템은 모두 처음 설계부터 이를 염두에 두었습니다.

Quantum의 고성능의 핵심은 스파스 셋 ECS 메모리 모델(메모리 정렬 데이터 구조 및 사용자 지정 힙 할당자 - 시뮬레이션 코드에서 런타임에 가비지 콜렉션 없음에 기반을 둠)과 결합된 포인터 기반 C# 코드를 사용하는 것입니다.

목표는 예측/롤백 접근 방식에 내재된 입력 오차로 인한 재시뮬레이션을 포함하여 대부분의 CPU 부하를 뷰/렌더 코드(유니티)에 남겨 두는 것입니다.

Quantum hyper-fast predict/rollback
Quantum은 CPU 부하를 렌더링 업데이트에 필요한 것에 대부분 남겨두고 시뮬레이션 코드를 최대한 빨리 실행하도록 설계되었습니다.

포인터 기반 C#의 사용은 (성능을 위해) 노출되지만, 사용자 지정 DSL 및 자동 코드 생성의 교묘한 사용으로 인해 대부분의 복잡성이 개발자로부터 숨겨집니다.

코드 생성

Quantum에서는 모든 게임 플레이 데이터(게임 상태)는 스파스 셋 ECS 데이터 구조(엔티티와 컴포넌트) 내에 보관되거나 사용자 지정 힙-할당자(동적 콜렉션 그리고 사용자 지정 데이터)로 항상 blittable 메모리 정렬 C# 구조체로 보관됩니다.

이에 포함되는 모든 데이터 구조를 정의하기 위해 개발자는 성능 지향적인 제한 대신 게임 컨셉에 집중할 수 있는 사용자 지정 DSL(도메인별 언어)을 사용합니다.

C#

// components define reusable game state data groups

component Resources 
{
  Int32 Mana;
  FP Health;
}

// structs, c-style unions, enums, flags, etc, can be defined directly from the DSL as well
struct CustomData 
{
  FP Resources;
  Boolean Active;
}

위의 코드는 해당 유형(명확한 메모리 정렬 포함), 직렬화 코드 및 특수 유형(컴포넌트와 같은)에 대한 모든 보일러 플레이트 제어 로직을 생성합니다.

자동 생성 API를 사용하면 게임 상태를 쿼리하고 수정하여 엔티티를 반복, 수정, 생성 또는 제거할 수 있습니다(구성 기반):

C#

var es = frame.Filter<Transform3D, Resources>();
// Next fills in copies of each of the components + the EntityRef
while (es.NextUnsafe(out var entity, out var transform, out var resources)) {
  transform->Position += FPVector3.Forward * frame.DeltaTime;
}

스테이트리스 시스템

Quantum의 DSL은 엔티티, 컴포넌트 및 보조 구조(구조, 열거, 유니언, 비트셋, 컬렉션 등)와 같은 개념으로 게임 상태 데이터 정의를 다루지만, 이 게임 상태를 업데이트하는 사용자 지정 게임 로직을 구성할 수 있는 방법이 필요합니다.

Systems를 구현하여 사용자 지정 로직을 작성할 수 있습니다. 이 로직은 Quantum의 클라이언트 시뮬레이션 루프를 통해 모든 체크 업데이트를 실행할 상태 비저장 로직의 일부입니다.

C#

public unsafe class LogicSystem : SystemMainThread
{
  public override void Update(Frame f) 
  {
    // your game logic here (f is a reference for the generated game state container).
  }
}

Systems API 게임 루프 호출 순서, 시스템 간 통신(물리 엔진 충돌 콜백 등 사용자 지정 및 사전 구축) 신호, 이벤트 및 기타 여러 확장 후크입니다.

이벤트

시뮬레이션은 Unity의 API를 직접 참조하지 않고 순수 C#로 구현되지만, 게임 플레이 코드가 렌더링 엔진과 통신할 수 있도록 하는 이벤트 및 에셋 연결 시스템의 두 가지 중요한 기능이 있습니다.

이벤트는 게임 코드가 시뮬레이션 중에 중요한 일이 발생했음을 렌더링 엔진에 알리는 방법입니다.
한 가지 좋은 예는 캐릭터가 데미지를 받을 때입니다.

이전 섹션의 상태를 기준으로 하여 손상되면 캐릭터 엔터티의 리소스 컴포넌트에서 상태 값이 감소한다고 가정합니다.
유니티 렌더링 스크립트에서 눈에 띄는 유일한 데이터는 손상 원인 및 이전 상태 값 등을 파악할 수 있는 방법 없이 새 상태 값 자체입니다.

파일 DSL 내의 이벤트 정의:

C#

event Damage 
{
    entity_ref Character;
    FP Amount;
}

게임 플레이 코드는 간단한 API 호출(발생됨)로서 이벤트를 발생시킵니다:

C#

public void ApplyDamage(Frame f, EntityRef c, FP amount) 
{
  // missing here, the logic to apply damage to the character itself
  
  // this sends an event to the "view" (Unity)
  f.Events.Damage(amount, c);
}

Quantum의 이븐 프로세서는 체크 업데이트가 완료된 후 생성된 모든 이벤트를 처리하여 서버 확인 입력, 이벤트 반복, 시뮬레이션 롤백 발생 시 취소/확인이 필요한 이벤트를 처리합니다.

그런 다음 시뮬레이션 코드에서 생성된 이벤트는 유니티 스크립트에서 생성된 콜백에서 런타임으로 사용할 수 있습니다:

C#

public void OnDamage(DamageEvent dmg) 
{
  // instantiate and show floating damage number above the target character, etc
}

에셋 링킹

유니티는 유연한 편집기와 매끄러운 에셋 파이프라인으로 알려져 있습니다.
에셋 링킹 시스템을 사용하면 게임 및 레벨 설계자가 유니티 편집기에서 데이터 기반 시뮬레이션 개체를 만들고 편집할 수 있으며, 이 개체를 시뮬레이션에 사용할 수 있습니다.
이것은 게임 플레이에 마지막 밸런스를 맞추기 위해 프로토타입 제작에 모두 필수적입니다.

개발자는 C# 시뮬레이션 프로젝트에서 원하는 속성을 노출하는 데이터 기반 클래스를 만듭니다:

C#

public partial class CharacterClass 
{
  public Int32 MaxMana;
  public FP MaxHealth;
}

그런 다음 유니티 레벨에서 설계자는 필요한 만큼 이 에셋의 인스턴스를 만들 수 있으며 각 인스턴스는 고유한 GUID로 자동으로 할당됩니다.

Character Classes - Asset Linking
에셋 링킹 시스템의 예: 유니티 에디터에서 직접 생성/수정하는 데이터 기반 문자 클래스 에셋 컨테이너입니다.

그런 다음 프로그래머는 시뮬레이션 내부에서 이러한 에셋의 데이터를 직접 사용할 수 있습니다:

C#

var data = frame.FindAsset<CharacterClass>("character_class_id");
var mana = data.MaxMana;

또한 이러한 에셋을 상태 정의 DSL에서 엔티티 및 구성요소에 직접 할당할 수도 있습니다:

C#

component CharacterAbilities 
{
  asset_ref<CharacterClass> CharacterData;
}

결정론적 라이브러리

Quantum에서 시뮬레이션은 모든 클라이언트에서 동일한 입력 값을 사용하는 경우 동일한 결과를 계산해야 합니다.
즉, 부동변수나 더블 변수를 사용하지 않고 벡터, 물리엔진 등과 같은 Unity API의 어떤 것도 사용하지 않는 결정론적이어야 합니다.

게임 개발자들이 이러한 게임 플레이 스타일을 구현하도록 돕기 위해 Quantum은 유연하고 확장 가능한 결정론적 라이브러리와 함께 제공됩니다. 이 라이브러리는 클래스/구조체/함수 집합과 DSL로 엔티티를 정의할 때 직접 사용할 수 있는 일부 컴포넌트와 함께 제공됩니다.

다음의 모듈을 사용할 수 있습니다:

  • 결정론적 수학 라이버러리: float/double 대체를 위한 FP (고정 소수점) 유형 (Q48.16), FPVector2, FPVector3, FPMatrix, FPQuaternion, FPRandom, FPBounds2, 그리고 안전한 캐스트 그리고 원시 유형으로부터 parse를 포함한 모든 추가 수학 유틸.
    수학 라이브러리는 성능을 주요 목표로 하여 구현되기 때문에 가능하면 항상 인라이닝, 룩업 테이블 및 빠른 연산자를 집중적으로 사용합니다.
  • 2D 및 3D 물리 엔진: 정적 및 동적 객체, 콜백, 조인트 등을 지원하는 고성능 상태 비저장 2D/3D 물리 엔진
  • NavMesh/PathFinder/Agents: 기존 Unity navmesh의 내보내기 도구 또는 메시를 직접 조작하는 편집기가 모두 포함. 또한 산업 표준 HRVO 충돌 방지, funneled paths 그리고 더 많은 기능이 포함됩니다.

다음에 학습할 사항

Quantum을 시작하려면 Quantum 100 시리즈부터 시작하는 것이 좋습니다. 이 자습서에서는 Quantum을 시작하는 데 필요한 모든 기본 사항을 설명합니다. 텍스트와 비디오 형식을 제공합니다.

Back to top