9.3. PiaClone 詳細仕様

PiaClone におけるデータの到達保証

UnreliableCloneElement

UnreliableCloneElement で共有される値は到達保証がされませんので、 値を設定したとしても受信側でその値になるとは限りません。

ReliableCloneElement

ReliableCloneElement は、「設定された値が最終的に共有された状態にする」という事を保証します。

例えば、値に 1 -> 2 -> 3 と順番に設定したとしても、受信側では 1 -> 3 と途中の値を飛ばして取得される場合があります。

ゲーム途中から ReliableCloneElement で値を受信することになった場合、過去に設定されたまま値が新たに設定されない状況でも自動的に再送が行われ、最新の値が取得されます。

ReliableCloneElement で送信中のステーションが異常切断(CloneProtocol のステートが State_Inactive でない状態でのセッション離脱)した場合は、残ったステーション間で最新の値を送りあうことにより残ったステーションで同じ値が取得されます。

EventCloneElement

EventCloneElement は、接続中に発行されたイベントがすべて順番通りに受け取れる事が保証されます。

例えば、1 -> 2 -> 3 と発行された場合、必ず 1 -> 2 -> 3 と受け取れます。

途中から EventCloneElement でイベントを受け取ることになった場合、その時以降に発行されたイベントは受け取ることが保証されますが、それ以前のイベントは受け取ることができません。

EventCloneElement で送信中のステーションが異常切断した場合でも、残ったステーション間で受信イベントの同期(受信したイベントを送り合い、補い合う処理)が自動的に行われます。ただし、 AtomicSharingClone の EventCloneElement を使用中に、送信途中の異常切断と別のステーションでのロック取得とその直後のイベントの発行が重なった場合に、タイミングによってはイベント同期失敗(受信イベントがステーション間で一致しなくなる)が発生します。イベント同期失敗を検出した場合は、 EventCloneElement::IsEventDropped() が true を返す状態になり、CloneProtocol::GetError() が ErrorType_EventDropped を返す状態になります。同期失敗が発生したイベントがアプリケーションにとって問題ない場合はそのままゲームを継続することができますが、問題がある場合はエラーとして CloneProtocol での通信を終了する必要があります。異常切断が発生してもセッションの整合性は保たれていますので、セッションを終了する必要はありません。

ReckoningCloneElement

ReckoningCloneElement では、それぞれの標本値を追加する際にその標本値の送信に到達保証が必要かどうかを設定できます。ReckoningCloneElement は UnreliableCloneElement の代替機能となり、随時新しい標本値が追加されていくことを想定しているため、ReliableCloneElement ほど厳密な到達保証を行っていません。

例えば、標本値のバッファのサイズが 3 で、 1 -> 2 -> 3 -> 4 -> 5 と標本値を採用するうちの 2 が到達保証を必要とされていたとします。送信側で 4 まで標本値に追加された時に、受信側へ 2 と 4 が届いていなかったとすると、送信側では到達保証の必要な 2 を再送します。しかし、その前に 5 が追加されると、 2 はバッファからあふれてもう送られません。その後 5 が届いた場合、受信側では 1, 3, 5 が届いたことになり、到達保証された 2 が飛ばされたようになります。

ReliableLargeCloneElement

ReliableLargeCloneElement は、「設定された値が最終的に共有された状態にする」という事を保証します。

ReliableCloneElement と基本的には同じですが、ReliableLargeCloneElement は 1 つのパケットに収まらない大きなサイズのデータも送受信することができます。

通信終了時の処理

CloneProtocol による通信中にクローンの登録を解除する場合は、必要な送信を終えてから登録解除が完了することが保証されます。

CloneProtocol::Stop() で通信を終了する場合は、必要な送信と受信を終えてから終了が完了することが保証されます。

アプリケーションで SerializePolicy を定義する場合

クラスや構造体など、基本型以外の型を直接クローンエレメントにセットする場合、必ず SerializePolicy を定義する必要があります。

Type 型をシリアライズするクラスには、以下の3つの関数が定義されている必要があります。

 

static void Serialize(void* pBuffer, const Type& value);

value をシリアライズした値を pBuffer に書き込みます。書き込み先のサイズは GetSerializedSize() です。pBuffer は4バイトアライメントされていない場合があります。

 

static void Deserialize(Type* pValue, const void* cpData);

cpData を読み込んでデシリアライズし、pValue に書き込みます。読み込み元のサイズは GetSerializedSize() です。cpData は4バイトアライメントされていない場合があります。pValue は、使用するクローンエレメントが適切に配置されていれば、Type にとって適切なアライメントがされています。

 

static uint32_t GetSerializedSize();

Type をシリアライズしたデータのサイズを定義します。また、シリアライズしたサイズが CloneProtocol::GetElementSizeMax() を超えるシリアライズはできません。CloneProtocol::GetElementSizeMax() は使用するネットワークモジュール(PiaInet など)やそこで設定する MTU の設定によって値が変わりますので注意してください。

送受信するメッセージの圧縮 

PiaClone で送受信するメッセージを圧縮されたものにすることができます。

送受信するメッセージを圧縮されたものにすると通信量を低減することができ、より多くのデータを同期できたり、同期したいデータ量は同じでもより安定した通信が期待できます。

一方で、メッセージを圧縮すると、圧縮/解凍の処理を行うために計算量は増加します。圧縮/解凍の処理は common::Scheduler::Dispatch() の中で行われます。

圧縮機能を使用するかどうかは、CloneProtocol::Setting::dataCompressionLevel で指定できます。

データの圧縮には zlib アルゴリズムが用いられます。冗長性の乏しいデータであったり、ごく小さなサイズのデータを圧縮しようとした場合は、圧縮処理後のサイズがかえって増加してしまう可能性があります。