9.1. PiaClone の概念

PiaClone の構造

PiaClone は以下の 3 段階(クローンエレメント、クローン、CloneProtocol)の階層構造になっています。

クローンエレメント

クローンエレメントは状態同期通信を行うデータの最小単位になります。ステーション間で同期(共有)する個々の値を管理します。同期方法によって CloneElementBase を継承した以下の 5 種類のテンプレートクラスが用意されています。

  • UnreliableCloneElement

設定された値を一度だけ送信します。パケロス時などには値が届かない場合があります。

主に、頻繁に更新される値に使用します。

  • ReliableCloneElement

設定された値の最新のものを到達保証を行うことにより確実に共有します。

主に、更新頻度は低いが確実に伝えたい値に使用します。

  • EventCloneElement

設定された値(イベント)の各々を全てを到達保証を行い、確実に共有します。

主に、何かイベントが発生した時にのみ送信し、全てのデータが順番も正しく届く必要がある値に使用します。

  • ReckoningCloneElement

値の変更時にその間を推測することにより、値の変更頻度を減らすことで通信量を抑えることができます。ReckoningCloneElement は他のモジュールである PiaReckoning の中にあります。

主に、UnreliableCloneElement で送信すると通信量が大きくなってしまい、多少誤差があっても問題ない値に使用します。

  • ReliableLargeCloneElement

ReliableCloneElement と同様に、設定された値の最新のものを到達保証を行うことにより確実に共有します。

1 つのパケットに収まりきらず、ReliableCloneElement を使用できない、サイズの大きな値を共有する場合に使用します。

 

クローンエレメントは、ゲームオブジェクトの位置や姿勢を表すベクトルや行列、ゲームオブジェクトのパラメータ構造体、などの粒度で使用されることを想定しています。

クローンエレメントを細かくわけて数が多くなるとヘッダ部分が増えて総通信量は増えてしまいます。逆に、1 つにまとめすぎるとクローンエレメントに設定した値の一部しか変更していないのに全てを送信することになってしまうので、やはり通信量は増えてしまいます。基本的には、同時に更新される値を 1 つのクローンエレメントに割り当てる事を推奨します。

クローン

クローンは複数のクローンエレメントから構成されており、クローンエレメントに値を設定できる権限を管理します。値を設定できる権限の制御の仕方によって、CloneBase を継承した以下の 4 種類のクラスが用意されています。

  • SendClone

常に設定権を持ちます。

ReceiveClone に値を送信するために使用します。

  • ReceiveClone

常に設定権を持ちません。

SendClone から値を受信するために使用します。

  • AtomicSharingClone

ロックに成功したときのみ設定権を持つことができます。

設定を行うステーションを排他制御する(1 つに制限する)ために使用します。

  • SequentialSharingClone

全ステーションが常に設定権を持ち、いつでも値を設定できます。

どのステーションでも設定できるようにするために使用します。EventCloneElement と ReckoningCloneElement は整合性が保証できなくなるため SequentialSharingClone に登録することはできません。

クローンは、ゲームオブジェクト、アイテム、などの粒度で使用されることを想定しています。

CloneProtocol

CloneProtocol は複数のクローンを登録することができ、PiaClone 全体を管理します。

Pia のプロトコルの 1 つとして用意されており、以下の機能を持ちます。

  • PiaClone を用いた通信の開始、終了の制御と全体的な状態の管理
  • 使用するクローンの登録、登録解除
  • ステーション間で同期された時刻の管理
  • エラー状態の管理

クローンエレメントの ID とクローンの ID

クローンエレメントは、クローンに登録する際に ID を割り当て、その ID によって識別されます。クローンエレメントの ID は、登録するクローン毎に独立して管理されますので、別のクローンに同じ ID を持つクローンエレメントを登録しても別のものとして扱われます。

値を共有しあうクローン間で同じ ID に登録するクローンエレメントは、(テンプレート引数も含めて)同じ型が登録されるように注意してください。型が異なっていた場合の動作は不定です。

クローンについても同様に、CloneProtocol に登録する際に ID を割り当て、その ID によって識別されます。クローンの ID は、クローンの種類ごとに独立しています。異なる種類のクローンで同じ ID を指定することができ、それぞれ別のものとして扱われます。

SendClone で設定される値は、同じ ID の ReceiveClone で取得できます。SendClone の ID は、ステーションごとに独立して設定することができ、ReceiveClone ではどのステーションのどの ID のSendClone から値を受け取るかを設定します。ReceiveClone が自ステーションの SendClone から値を受け取るようにすることも可能です。

AtomicSharingClone、SequentialSharingClone は、それぞれ同じ ID 同士で値のやり取りを行います。

クローン登録の例

クローン登録の例を図に示します。図 9-1. クローン登録の例 では、各ステーションに ID が 1 の Clone がそれぞれ 5 個ずつ登録されていますが、クローンの種類や ReceiveClone の SendStationIndex が異なるためそれぞれ別のものとして扱われます。そして、それぞれに登録された同じ ID のクローンエレメント同士の間で値が共有されます。

StationIndex_1 にある Id : 1 である SendClone に登録されている Id : 1 の UnreliableCloneElement に 100 という値を設定した場合は、各ステーションにある Id : 1、SendStationIndex : StationIndex_1 の ReceiveClone にある Id : 1 の UnreliableCloneElement で 100 という値を受け取ることができます。

図 9-1. クローン登録の例

 

各クローンエレメントのユースケース

各クローンエレメントの実際のゲームでの使用例について説明します。

  • UnreliableCloneElement
    各プレイヤのキャラクタの位置、向き
    アイテムの位置
    NPC の位置

  • ReliableCloneElement
    各プレイヤのキャラクタの HP(体力)
    各プレイヤのキャラクタが持っている武器

  • EventCloneElement
    各プレイヤ間の攻撃の当たり判定結果
    アイテムの取得
    アイテムの使用

  • ReckoningCloneElement
    各プレイヤのキャラクタの位置、向き
    NPC の位置

  • ReliableLargeCloneElement
    各プレイヤやオブジェクトの状態

 

参考:

ReliableCloneElement と EventCloneElement には次の違いがあります。

ReliableCloneElement は、最新の値以外の古い値はもし受信していない人がいても再送されません。EventCloneElement は、設定した値が全て順番も正しく確実に届きます。EventCloneElement の方が ReliableCloneElement より通信量が大きくなります。

各クローンのユースケース

各クローンの実際のゲームでの使用例について説明します。

  • SendClone、ReceiveClone
    各プレイヤのキャラクタ

  • AtomicSharingClone
    排他制御や先取り判定が必要なオブジェクト
    落ちているアイテム
    乗り物

  • SequentialSharingClone
    排他制御が必要なく、どのステーションからでも自由に更新してよいオブジェクト
    建造物の破壊状態

 

参考:

AtomicSharingClone と SequentialSharingClone には次の違いがあります。

AtomicSharingClone は、値を設定できるステーションをロックによって固定できます。例えば 1 人しか取れないアイテムを取ったイベントの発行や、そのアイテムを運んでいるときの位置を設定する場合などに使用できます。SequentialSharingClone は、どのステーションからもロックなしで値を設定することができます。例えば複数のステーションが同時に値を設定したとしても、最終的な値がわかればよい場合などに使用できます。AtomicSharingClone の方が SequentialSharingClone より通信量が大きく、ロック待ちのため遅延も大きくなります。