quantum | v2 switch to v1  

Quantum イントロ

概要

Photon Quantumは、Unityで作られたオンラインマルチプレイヤーゲームのための高性能決定論的ECS(エンティティコンポーネントシステム)フレームワークです。

アクションRPG、スポーツゲーム、戦闘ゲームなどのレイテンシに敏感なオンラインゲーム用に設計されています。

Quantumは以下のような要素で構築された最先端の技術スタックを搭載しています。

・サーバーマネージド予測・ロールバックシミュレーションコア ・スパース集合ECSメモリモデルおよびAPI(SDKバージョン2で新登場) ・ステートレス決定性ライブラリ完備(マス、2Dおよび3D物理、ナビゲーションなど) ・リッチなUnityエディタ統合とツーリング

すべて、業界で証明され、成熟した既存のPhoton製品およびインフラストラクチャを加えてビルドしています(トランスポートレイヤーとしてPhoton Realtime、サーバーロジックをホストするためのPhoton Serverプラグインなど)。

次の図が表すこと:

Quantum Architecture
Quantumアーキテクチャ概要とサーバ側のプラグインとクライアント側のシミュレーション(ユーザが開発したカスタムゲームロジックを含む)

Back To Top

ロックステップなしの決定論

決定論的なシステムでは、ゲームクライアントは、すべてのクライアント上でローカルに実行されているシミュレーションでプレーヤーの入力を交換するだけです。 過去には、ゲームクライアントがシミュレーションの各ティック/フレームを更新する前に、他のすべてのプレイヤーからの入力を待つロックステップアプローチを使用していました。

Quantumでは、ゲームクライアントは入力予測を使用してシミュレーションをローカルに自由に進めることができ、高度なロールバックシステムがゲームの状態を復元し、誤予測を再シミュレーションします。 ​

Quantumは入力レイテンシとクロック同期を管理するためにゲームに依存しない信頼できるサーバコンポーネント(Photonサーバプラグイン)に依存するため、クライアントは最遅のものをロールバックして前方を確認する必要はありません。

以下はQuantumゲームの基本のビルドブロックです。

  • Quantum Server Plugin: ゲームクライアント間の入力タイミングと配信を管理し、クロック同期ソースとして機能します。 顧客がホスティングするバックエンドシステム(マッチメイキング、プレイヤーサービスなど)と統合するために拡張することができます。

  • Game Client Simulator: Quantumサーバと通信し、ローカルシミュレーションを実行し、すべての入力予測とロールバックを実行します。

  • Custom Gameplay Code: Quantum ECSを使用して、孤立した(Unityから切り離された)純粋なC#シミュレーションとして開発されました。 QuantumのAPIは、高性能なコードの編成の枠組みを提供するだけでなく、決定論的な3Dベクトル計算、2D物理エンジン、navmeshパスファインダー、アニメーターなどのあらゆるゲームで再利用できる、あらかじめ構築されたコンポーネント(データ)とシステム(ロジック)を提供します。

Back To Top

従来のコーディング

Quantumの高性能の鍵は、安全でないC#コード(Cスタイルのポインタ、メモリアライメントされたデータ構造体、実行時の直接割り当て/ガベージコレクションを行わない)の使用です。

ポインタベースのC#の使用は(パフォーマンスのために)公開されていますが、カスタムDSLと自動コード生成を巧みに使用することで、開発者に複雑さを感じさせません。

Back To Top

コード生成

Quantumでは、すべてのゲームプレイデータ(ゲーム状態)は、メモリ配列のC#構造体として単一のブロックに構成されています。

開発者は、すべてのデータ構造を定義するために、パフォーマンス指向の制約の代わりにゲームの概念に専念できるカスタムDSL(ドメイン固有の言語)を使用します

// 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;
}

上記のコードスニペットは、最大32文字のゲーム状態データ構造を生成し、それぞれに変換とリソースの両方のコンポーネントが含まれています。

自動生成APIを使用すると、エンティティの読み込み、変更、作成、破棄を行う包括的な機能を使用して、ゲームの状態を参照および変更することができます。 ​

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)) {
  t->Position += FPVector3.Forward * frame.DeltaTime;
}

Back To Top

ステートレスシステム

QuantumのDSLは、エンティティ、コンポーネント、補助構造体(構造体、列挙体、連合体、ビットセット、コレクションなど)などの概念によるゲームステートデータ定義を対象としていますが、ゲームステートを更新するカスタムゲームロジックを整理する方法が必要です。

Quantumのクライアントシミュレーションループによって毎回更新されるステートレスなロジックであるシステムを実装することで、カスタムロジックを作成します。

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ゲームループの呼び出し順序、システム間通信(物理エンジンコリジョンコールバックなどのカスタムおよびプレビルドの両方)、イベントおよびその他の拡張フック。

Back To Top

イベント

シミュレーションは、UnityのAPIを直接参照することなく純粋なC#で実装されていますが、ゲームプレイコードとレンダリングエンジンとの通信を可能にする重要な2つの機能としてイベントとアセットリンキングシステムが使用されます。

イベントは、ゲームコードがシミュレーション中に重要なことが発生したことをレンダリングエンジンに知らせるための方法です。

例えば、キャラクターにダメージを与える出来事などです。

前のセクションのステートを基にして、ダメージがキャラクタエンティティのリソースコンポーネントからHP値を減少させるのを想像してください。

Unityのレンダリングスクリプトで唯一明確になっているデータは、新しいHP値そのものです。ダメージの原因や以前のHP値などを知ることはできません。

ファイルDSL内のイベント定義:

event Damage
{
    entity_ref Character;
    FP Amount;
}

ゲームプレイコードは、単純なAPIコール(生成された)としてイベントを発生させます。

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のイベントプロセッサは、チックの更新が完了した後に生成されたすべてのイベントを処理し、サーバが確認した入力、イベントの繰り返しなどを必要とするイベントを処理します。

シミュレーションコードから生成されたイベントは、Unityスクリプトで作成されたコールバックから実行時に消費されます。

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

Back To Top

アセットリンキング

Unityは柔軟なエディタとスムーズなアセットパイプラインを用意していることで有名です。

ゲームデザイナーやレベルデザイナーはアセットリンキングシステムによりUnity Editorからデータ駆動型シミュレーションオブジェクトを作成して編集し、シミュレーションに入力できます。

これは、最終的なタッチをゲームプレイに追加するためのプロトタイプに不可欠です。

開発者は、C#シミュレーションプロジェクトから適切な属性を公開するデータ駆動型クラスを作成します。

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

Unityのレベルデザイナーは、必要に応じてこのアセットのインスタンスをいくつでも作成することができます。それぞれのインスタンスには、一意のGUIDが自動的に割り当てられます。

Character Classes - Asset Linking
アセットリンキングシステムの例: データ駆動型の文字クラスアセットコンテナは、Unity Editorから直接作成または変更されます。

プログラマーはこれらのアセットのデータをシミュレーション内から直接使用できます。

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

ステート定義DSLからコンポーネントに直接これらのアセットをリファレンスすることもできます。

component CharacterAbilities{
    asset_ref<CharacterClass> CharacterData;
}

Back To Top

決定論的ライブラリ

Quantumでは、同じ入力値を使用する場合、シミュレーションはすべてのクライアントで同じ結果を計算する必要があります。

つまり決定論的であり、フロート変数や倍精度変数、ベクトル、物理エンジンなどのUnity APIのいずれも使用していないことを意味します。

ゲーム開発者がこのスタイルのゲームプレイを実現するために、Quantumには、クラス/構造体/関数のセットと、DSLでエンティティを定義するときに直接使用できるいくつかのコンポーネントの両方を含む、柔軟で拡張可能な決定論的ライブラリがバンドルされています。

以下のモジュールが利用可能です:

  • 決定論的な数学ライブラリ:float/doubleの代わりとなるFP (Fixed Point) 型 (Q48.16)、FPVector2、FPVector3、FPMatrix、FPQuaternion、FPRandom、FPBounds2、および安全なキャストを含む余分な数学ユーティリティ、ネイティブタイプのパーサー。

数学ライブラリはパフォーマンスを第一の目標として実装されているため、可能な限りインライン展開、ルックアップテーブル、高速演算子を使用します。

  • 2D ・3D物理エンジン: 静的および動的オブジェクト、コールバック、ジョイントに対応する高性能ステートレス2D・3D物理エンジン。
  • NavMesh + A* PathFinder: 既存のUnity navmeshからのエクスポータまたはメッシュを直接操作するエディタの両方を含みます。経路探索の他に、視線確認を行うことができます。

まだまだお伝えしたいことがありますので、このドキュメントのマニュアル部分(現在準備中)をぜひご覧になってください。

To Document Top