18. 有用な機能、参考情報

ゲームプログラム構築のための有用な機能、参考情報について説明します。

18.1. パフォーマンスの微調整

このセクションでは、ゲームの微調整のために NetZ に用意されているクラスについて説明します。 これらのクラスを使用すると、転送プロトコルやデータセット更新のさまざまな局面を監視したり、デフォルトのメモリ割り当て関数を変更したりできます。 そのため、微調整プロセスを促進し、さまざまなネットワーク条件をシミュレーションして、異なる条件下でのゲームのパフォーマンスを見ることができます。

18.1.1. ネットワークエミュレーション

EmulationDevice クラスを使用すると、ステーションの転送デバイスの帯域幅、ジッタ、遅延、パケットロス率といった、 特定のネットワーク条件をエミュレートできます。

このクラスの InputEmulationDevice サブクラスを使用すると、入力デバイス設定にアクセスでき、 OutputEmulationDevice を使用すると出力設定にアクセスできます。 これらのクラスを使用すると、さまざまなネットワーク条件下でゲームのパフォーマンスをテストできます。 これらには、RootTransport の GetInputEmulationDevice メソッドと GetOutputEmulationDevice メソッドを通じてアクセスする必要があります。 RootTransport のインスタンスは NetZ の作成と同時に有効になります。 その後 EmulationDevice オブジェクトへの参照を取得し、独自の Enable メソッドを使用してオブジェクトを有効にできます。

例えば、次のコードではステーションの転送デバイスで、bandwidth で指定される帯域幅[bps]、latencyで設定される遅延[msec]、 dropProbaiblityで設定されるロスレートでのパケットロスのネットワークエミュレーションを行います。

Code 18.1 出力ネットワークエミュレーション設定
OutputEmulationDevice * pOutputEmulation =
                RootTransport::GetInstance()->GetOutputEmulationDevice();
pOutputEmulation->Enable(); //Enableの後に、値を設定すること
pOutputEmulation->SetBandwidth(bandwidth);
pOutputEmulation->SetLatency(latency);
pOutputEmulation->SetPacketDropProbability(dropProbaiblity);

入力に対するInputEmulationDeviceも利用可能ですが、通常は、OutputEmulationDeviceにのみ利用すればよいでしょう。

18.2. データ記録

データは Log クラスによってログに記録されます。 EventLog クラスと TraceLog クラスはこのクラスのサブクラスで、それぞれシステムイベントとトレースの記録に使用されます。 EventLog オブジェクトと TraceLog オブジェクトにはそれぞれ、データが出力される場所とそのフォーマットを定義するために、 LogDevice オブジェクトと OutputFormat オブジェクトが関連付けられている必要があります。 これらのオブジェクトは、それぞれ Log::SetLogDevice メソッドと Log::SetOutputFormat メソッドを使用して Log オブジェクトに関連付けられます。 LogDevice クラスまたはその任意のサブクラスは、特定のログデバイスにログ文字列を出力する方法を定義します。 ログデバイスには、ファイル、デバッガ、コンソール、ユーザー定義のデバイスが使用できます。 OutputFormat クラスはログに記録されたデータの示す情報を指定します。 例えば、スレッド ID、プロセス ID、ローカルタイム、トレース番号などの情報をトレースに含めることができます。 LogDevice クラスと OutputFormat クラスの両方にサブクラスを作成して、独自のカスタム出力デバイスとフォーマットを実装できます。

EventLog クラスは、ログレベルシステムを使用して永続ログ機能を実装します。 ログレベルはログメッセージの重要度を指定します。 これは、SetLogLevel メソッドを使用して設定され、Verbose、Info、Warning、Critical、Always (重要度の順)のいずれかになります。 ログの出力リクエストが行われると、特定のメッセージのレベルが EventLog オブジェクトの最低ログレベルより低い場合は、そのメッセージは表示されません。 例えば、ログレベルが Warning に設定されている場合、Verbose と Info のメッセージはログに記録されません。

EventLog クラスによって記録されたイベントメッセージは、QLOG メソッドを使用して定義されます。 このメソッドは、次の構文を持ちます。 lLevel はイベントのログレベルで、szFormat はログメッセージで、標準の printf 関数と同じフォーマットです。

Code 18.2 QLOG メソッドの構文
void QLOG(EventLog::LogLevel lLevel, qChar *szFormat, ... );

QLOG メソッドは、EventLog クラスを調べる必要がなく、直接呼び出すことができます。 例えば、Info レベルの「Begin test」というメッセージは、次のように定義できます。

Code 18.3 Info レベルのメッセージ出力
QLOG(EventLog::Info, NEX_T("\n\nBegin test"))

システムの動作は TraceLog クラスを使用してトレースできます。 このクラスはすべてのアクティブトレースを記録するので、プログラムのデバッグに便利です。 リリースモードで実行する場合には、トレースは自動的に記録されません。 複製オブジェクトプロトコル、フォルトトレランス、初期化、操作、プラグイン、ロビー、 更新などのシステムのさまざまな局面をトレースできるトレースマクロがいくつか定義されています。 例えば、システムの障害動作をトレースするには、次のトレースフラグを設定します。

Code 18.4 システムの障害動作をトレースするトレースフラグの設定
TraceLog::GetInstance->SetFlag(TRACE_FAULT);

また、独自のトレースを実装するために再定義できる TRACE_USER マクロと、取得できるすべての情報を簡単にトレースできる TRACE_ALL フラグもあります。 さまざまなトレースフラグは TraceLog::SetFlag メソッドと TraceLog::ClearFlag メソッドを使用して設定および消去できます。 TRACE_OPERATION フラグはシステムオペレーションに関連付けられ、デフォルトではすべてのオブジェクトの全操作をトレースします。 記録された操作とオブジェクトをフィルタリングするには、 セクション 10.1 に示すように Operation::SetTraceFilter システムコールバックを使用して記録する情報を定義する必要があります。

DO の状態をトレースするには、DuplicatedObject::Trace メソッドを使用します。 このメソッドは、ユーザーによって再定義することも、デフォルトの実装を使用することもできます DO のデフォルトのトレース情報は、 クラス名 DOHandle、複製のロール、参照カウント、デストラクションにフラグ指定されているかどうか、 DO マスターのインスタンスのあるステーションから構成されます。 例えば、SphereZ でカメラのフォーカスが変更される際に Sphere クラスの登録されているオブザーバーをトレースするには、次を使用します。

Code 18.5 Sphere クラスに登録されているオブザーバーのトレース
void Sphere::DoTakeFocus()
{
    // Other details of the implementation of the method
    else
    {
        DOHandle hObserver = INVALID DOHANDLE;
        Station::Ref refStation(Station::GetLocalStation());
        if(refStation.IsValid())
        {
            refStation->GetObserver(&hObserver);
        }
        TRACE( TRACE_ALWAYS, NEX_T("Observer: %X "), hObserver );
    }
}

また、ローカル DO ストアの内容は、DuplicatedObjectStore::Trace メソッドを使用してトレースできます。 これは事実上、ローカルステーションで現在インスタンス化されているすべてのオブジェクトに DuplicatedObject::Trace メソッドを呼び出すことです。

18.3. 複製オブジェクトのスケーラビリティ

ユーザーの使用体験の質を低下させることなくゲームを拡大するには、システムのリソース使用量を最適化する必要があります。 P2P セッションに参加するステーションが増えると、帯域幅やステーションと CPU の間でのレイテンシ、 また各ステーションのメモリなどのリソースを効率よく使用して、プレイヤーに感じられる品質が低下しないようにする必要があります。 ゲームを拡張可能にするため、NetZ の API には使用可能なシステムリソースをもっとも効率よく利用するために使用できる機能がいくつか用意されています。 上述のように、NetZ で使用される複製オブジェクトモデルでは、開発者は、オブジェクトが必要なステーションにのみ複製されるように、 パブリッシュされるオブジェクトのデュプリカの場所と数を制御できます。帯域幅の使用を削減するには、推測航法によるデータ推定を使用して、 オブジェクトデュプリカに送信する更新数を最小化できます。 これらの機能でゲームは拡張可能になりますが、当然ゲームが拡張される範囲は特定のゲームによって異なります。 NetZ は比較的小規模なゲーム用にデザインされていることに注意してください。

ゲームのスケーラビリティはゲームの種類と、 P2P セッションに接続されているステーション間に必要な対話レベルによって異なります。 当然ネットワークゲームの場合、ステーション間で送信が必要な情報が増えるほど、同時にサポートできるステーション数は少なくなります。 ステーションで受信する必要のある情報量は、オブジェクト数、 データセットの更新が必要な頻度、ステーションに必要な出力品質などの要因によって異なります。 NetZ では、作成できる DO とクラスの数に関する固有な制限がありますが、実際には制限にならないようにする必要があります。 1 つのゲームで作成できる DO クラスの最大数は、2^10、つまり 1024 クラスで、 1 つのゲームで作成できる DO マスターオブジェクトインスタンスの最大数は 2^22、つまり 400 万以上の DO マスターです。 特定のクラスでの DO マスターオブジェクト数への制限は、各オブジェクトを個別に識別するために DO クラス当たり 22 ビットが使用されていることが起因します。 DO マスターとデュプリカは同じ ID を使用するため、特定のマスターオブジェクトのデュプリカ数への制限はありません。 ゲームの実装方法にかかわらず、帯域幅、使用可能なメモリ、CPU などのハードウェアの物理的な制限は常に存在します。 ゲームによって、ハードウェアとソフトウェアの制限はパフォーマンスの問題になる場合とならない場合がありますが、 NetZ の柔軟性によってこのような制限の影響を最小限にする方法がいくつかあります。

帯域幅の使用は常にあらゆるネットワークで問題になりますが、ステーションで使用する帯域幅を最適化するには、影響する要因を理解する必要があります。 使用するハードウェアによって、ステーションには使用可能な入出力の帯域幅に制限があります。 ステーションで使用される入力帯域幅は、ステーションのデュプリカ数、メッセージのサイズ、オブジェクトのデータセットが更新される頻度によって異なります。

\[入力帯域幅 = デュプリカ数 * メッセージサイズ * メッセージ数/秒\]

メッセージサイズは、ペイロードに、オブジェクトやデータセットの ID などの情報を含むオーバーヘッドの 88Byte を追加した値です。 入力帯域幅の使用量を削減するには、データ推定を使用して、推定が正確ではなくなる場合にのみデータセットを更新するようにできます。 また、開発者はステーションに必要なデュプリカのコピーのみを作成するようにする必要があります。

ステーションで使用される出力帯域幅は、ステーションの DO マスター数、直接更新を送信するステーション数、メッセージのサイズと頻度によって異なります。

\[出力帯域幅 = マスター数 * 直接メッセージ数 * メッセージサイズ * メッセージ数/秒\]

ステーションが別のステーションに直接送信するメッセージ数は、通常オブジェクトのデュプリカ数と同じです。 ただし、デュプリカのデータセット値を予測する推定フィルタを使用して、 DO マスターが送信する必要のある更新数を最小化することができます。 そのため、データセットが変更されるたびに更新するのではなく、デュプリカの値が予測され、更新は予測が正確ではない場合のみに送信されます。 ネットワーク全体に DO マスターを分散して使用可能なリソースを最適化するために、オブジェクトのマイグレーションも実装できます。 オブジェクトのマイグレーションは、性能の低いステーションの DO マスターオブジェクト数を低下させ、 性能の高いステーションでの数を増加させるために使用し、各ステーションが帯域幅に相当した DO マスター数のみをコントロールするようにできます。

ステーションに必要な帯域幅は、主に送受信するメッセージ数によって異なります。 つまり、個別のメッセージを各デュプリカに送信する必要があるため、オブジェクトのデュプリカ数と、 オブジェクトのデータセットが更新される頻度によって異なります。 メッセージの受信に必要な帯域幅はステーションが更新を受信するオブジェクトデュプリカ数によって異なり、 メッセージの送信に必要な帯域幅は更新を送信する必要のある DO マスターのデュプリカ数によって異なります。 ステーションの帯域幅が限定されている場合、更新の頻度を低下することができます。 ただし、これはユーザーのゲーム体験の品質を低下させる場合があります。 各メッセージのサイズは送信する必要のあるデータセットのサイズと、各メッセージに含まれるヘッダーによって異なります。 ヘッダーは転送プロトコル情報と、パケット ID や宛先などの情報を含みます。

18.4. ネットワーク構成オプション

NetZ のアーキテクチャは柔軟性に優れているため、セクション 2.4 「ネットワークトポロジー」で説明されているように、 ゲームは真のP2Pモード、サーバークライアントモード、またはこの 2 つの両方で実行できます。 この柔軟性により、開発者にはゲームでのニーズに合わせてネットワークを構成する方法や、ハッカーを阻止するためなどの、 さまざまな方法でゲームを設定する際に使用できるさまざまなオプションが与えられます。 開発者によって選択されるアーキテクチャは、 分散制御型のパフォーマンスの利点と集中制御型のセキュリティ対策のどちらかを選択することになります。

NetZ ゲームでは、開発者には各オブジェクトの DO マスターがある場所、 ネットワークでデータが伝播される方法を完全にコントロールできるので、 特定のデータへのユーザーのアクセスを簡単に制限することができます。 例えば、真のサーバークライアントアーキテクチャを採用することなく、 特定のデータをセキュアサーバーに保管してアクセスを制限することができます。 開発者には、セキュアサーバーにすべてまたは一部の DO を配置するオプションがあります。 そのため、機密データをサーバーに配置し、非機密データを各ユーザーのステーションに配置することができます。 ハイブリッド手法を使用することで、開発者は高速通信やフォルトトレランスなどのP2Pキテクチャの多くの利点を保ちながら、 ハッカーの影響を効率よく最小限に抑えることができます。

制御形態を、分散制御型から集中制御型へ変換するには、 各オブジェクトの DO マスターのあるステーションを変更するだけで実行できます。 分散制御型では、ユーザーによってコントロールされているオブジェクトの DO マスターはユーザーのステーションにあります。 集中制御型で操作するには、開発者はすべての DO マスターを単一のセキュアステーションに配置することを選択して、 ユーザーがアクセスできる情報量を効果的に制限できます。 この場合、プレイヤーは RMC またはアクションを使用して自分のオブジェクトの DO マスターにコマンドを実行します。 サーバー状のアーキテクチャで NetZ を実行すると、ハッカーへの機会を効果的に低下できますが、 フォルトトレランスやレイテンシの低減などの、NetZ のP2Pベースの利点も排除してしまいます。 ただし、特定のゲームでは真のサーバークライアント構成での操作が効果的な場合があります。 実際にサーバーが複数のサーバーによるグループで構成されている場合、NetZ はサーバーグループ全体にフォルトトレランスを実装するために必要なすべてのインフラストラクチャを提供して、 サーバーに障害が発生してもサーバーの情報が維持されるようにします。

18.5. カスタム推測航法

NetZ の推測航法が要件に適さない場合、カスタム推測航法を使用して独自のカスタムスキームを実装できます。 この拡張では、独自のデータ推定モデルと、 DO マスターがデュプリカを更新する際に使用するスキーマを定義できます。

拡張を使用するには、カスタムモデルを実装するファイルに、次のように DeadReckoning.h ファイルをインクルードする必要があります。

Code 18.6 カスタム推測航法を使用する
#include <Extensions/DeadReckoning.h>

その後、独自のカスタム推測航法を実装するには、次の手順に従います。

  1. カスタムデータセット DDL プロパティを DDL ファイルに宣言します。
  2. dsproperty DDL 宣言で使用されるマクロを定義します。
  3. データ推定モデルを実装します。
  4. 用意されているスキーム以外のスキームが必要な場合は、カスタムモデルポリシーを実装します。
  5. DuplicatedObject::UpdateDuplicatedObject::Refresh を定期的に呼び出して、 DO マスターのデータセット値を更新し、デュプリカでその値をリフレッシュします。

18.5.1. カスタム DDL プロパティの宣言

独自のカスタム推測航法を実装するには、まず DDL ファイルで deadreckoning プロパティ識別子を使用して独自のカスタムデータセット DDL プロパティを宣言する必要があります。 例えば、MyOwnDeadReckoning DDL プロパティを作成するには DDL で次を宣言します。

Code 18.7 deadreckoning プロパティ識別子を使用したカスタムデータセット DDL プロパティの作成
dsproperty MyOwnDeadReckoning : deadreckoning;

カスタムデータセット DDL プロパティが宣言されると、それを適切なデータセットに指定できます。 次に例を示します。

Code 18.8 カスタムデータセット
dataset Position {
    float m_fX;
    float m_fY;
} MyOwnDeadReckoning;

通常、DDL プロパティは特定のデータセットに結合できます。 ただし、deadreckoning プロパティ識別子を指定する DDL プロパティは別の deadreckoning プロパティ識別子と結合することも、 内蔵の buffered や extrapolation_filter プロパティと結合することもできません。

18.5.2. マクロの定義

deadreckoning プロパティ識別子を使用して DDL プロパティを定義する場合、生成されるコードで次の 2 つのマクロを使用します。

Code 18.9 生成されるコードで使用するマクロ
// Defines the model used
_PR_MyDeadReckoningProperty_model(DS)
// Defines the model policy used
_PR_MyDeadReckoningProperty_modelpolicy

これらの 2 つのマクロを使用して、<DDLFileName>Properties.h ファイルで 2 つのマクロを定義して、 それぞれ使用する推測航法モデルとモデルポリシーを定義します。 最初のマクロは推定に使用されるモデルクラスの名前を定義します。 同じ推測航法モデルが複数のデータセットクラスに使用できる場合、テンプレートクラスが使用できます。

例えば、上述のように MySpecificDeadReckoning と MyGenericDeadReckoning dsproperty を DDL で定義し、 データセットを MySpecificModel と MyGenericModel の推測航法モデルと付属の SharedModelPolicy に関連付ける場合、 MyDDLProperties クラスのヘッダーファイルは次を定義します。

Code 18.10 MyDDLProperties クラスのヘッダーファイル
// Define that the model is used for a single dataset
#define _PR_MySpecificDeadReckoning_model(DS) MySpecificModel

// Define that the model is used for any dataset
#define _PR_MyGenericDeadReckoning_model(DS) MyGenericModel<DS>

// Define the model policy to use with the MySpecificModel model
#define _PR_MySpecificDeadReckoning_modelstore SharedModelPolicy

// Define the model policy to use with the MyGenericModel model
#define _PR_MyGenericDeadReckoning_modelstore SharedModelPolicy

18.5.3. 推測航法モデルの実装

推測航法モデルは、データセット値が時間の経過によって推定または内挿される方法を指定します。 モデルを実装するには、 DeadReckoningModel クラスを継承し、特定の API(IsAccurateEnough メソッド、 ComputeValue メソッド、UpdateModelOnMaster メソッド、UpdateModelOnDuplica メソッド)を実装するクラスを実装する必要があります。 これらのメソッドは、後述のとおり、DuplicatedObject::Update または DuplicatedObject::Refresh が呼び出され、更新が必要な場合に呼び出されます。 モデルが単一のデータセットのみで使用される場合は通常の C++ クラスとして、 複数のデータセットが同じモデルを使用する場合はテンプレートとして、モデルクラスを実行できます。 各実装の例を次に示します。

カスタム推測航法モデルは実装するか、<DDLFileName>Properties.h ファイルに含められる必要があります。 コードが生成される方法のため、モデルの関連データセットはこの同じファイルで前方宣言される必要があります。

Code 18.11 モデルクラスの実装
// This class only performs extrapolation of a Position dataset.
// Therefore, it is implemented as a regular C++ class and
// hardcodes the Position class in the API.
class MySpecificModel: public DeadReckoningModel {
    public:
        MySpecificModel();
        ~MySpecificModel() {};

        qBool IsAccurateEnough(const Position& oPosition, Time tUpdateTime,
                            DuplicatedObject* pUpdatedDO, Station* pTarget);
        void ComputeValue(Position* pPos, Time tTarget) const;

        void UpdateModelOnMaster(const Position& oCurrentValue,
                                Time tUpdateTime);
        void UpdateModelOnDuplica(const Position& oCurrentValue);
};

// This model is implemented as a template and as such may be used
// for any dataset. It could expect that the extrapolated dataset
// provides methods to access the X and Y parameters (GetX, SetX,
// GetY, SetY), for example.
template<class DS>
class MyGenericModel: public DeadReckoningModel {
    public:
        MyGenericModel();
        ~MyGenericModel() {};

        qBool IsAccurateEnough(const DS& oCurrentValue, Time tUpdateTime);
        void ComputeValue(DS* pValue, Time tTarget) const;

        void UpdateModelOnMaster(const DS& oCurrentValue, Time tUpdateTime);
        void UpdateModelOnDuplica(const DS& oCurrentValue);
};

18.5.3.1. 推測航法モデルポリシーの実装

カスタム推測航法を実装する際、付属のモデルポシリーのいずれかを使用するか、独自のポリシーを記述できます。 モデルポリシーは、 DO マスターが管理する推測航法モデルの数と、推測航法モデルがデュプリカに関連付けられる方法を記述します。 例えば、 DO マスターはすべてのデュプリカに単一のモデルのみを管理し、すべてのデュプリカが同一の方法で更新するようにすることも、 複数のモデルを管理して、距離ベースの推測航法が実装される場合などに、異なるデュプリカが別の方法で更新されるようにすることもできます。

SharedModelPolicy と PerStationModelPolicy の 2 つのモデルポリシーが用意されています。 共通モデルポリシーには、 DO マスターは推測航法モデルクラスの唯一のインスタンスをローカルでインスタンス化します。 このインスタンスはそのデュプリカのいずれかに更新が必要かどうかを決定するために使用されます。 そのため、同じモデルインスタンスが各デュプリカで使用されるので、モデルが正確でなくなり、更新が必要な場合にはすべてのデュプリカにメッセージが送信されます。 また、ステーションごとのモデルポリシーでは、 DO マスターはその各デュプリカに推測航法モデルクラスのインスタンスをローカルでインスタンス化し、 マスターがデュプリカと同じ数のモデルインスタンスを管理します。 モデルインスタンスは各デュプリカに管理され、デュプリカに更新が送信される必要があるかどうかを決定するために使用されるので、 各デュプリカはオブジェクトとプレイヤーのアバターの距離など、異なるスキームに従って更新できます。 Figure 18.1 は 2 つの付属モデルの概略を示します。

../_images/Fig_Construction_Shared_PerStation_ModelPolicy.png

Figure 18.1 共有およびステーション毎のモデルポリシーの概略図

付属のモデルポリシーがどちらも要件に合わない場合は、簡単に独自のポリシーを実装できます。 この実装には、次に説明する 3 つのメソッドを実装する独自のモデルポリシークラスを記述します。 例については、DeadReckoningDSDecl クラス、付属の SharedModelPolicy ポリシーと PerStationModelPolicy ポリシー、 およびこれらのメソッドの実装の詳細を参照してください。

Code 18.12 独自モデルポリシーの実装
template<class MODEL>
class MyModelPolicy {
    public:

        // Returns a Duplication master’s local instance of one
        // of its duplica’s dead reckoning models.
        MODEL* GetRemoteDeadReckoningModel(const Station* pTargetStation);

        // Returns a duplica’s local instance of the dead
        // reckoning model.
        MODEL* GetLocalDeadReckoningModel();

        // Removes a Duplication master’s local instance of one of
        // its duplica’s dead reckoning models. This method only
        // needs to be defined if the duplication master maintains
        // more than one model.
        void ClearRemoteDeadReckoningModel(const Station* pTargetStation);
};

18.5.3.2. データベースの更新とリフレッシュ

NetZ の標準の推測航法スキーム同様、デュプリカのデータベースが正しく更新されるように、 DO マスターのデータセット変数を DuplicatedObject::Update で、 その後に DuplicatedObject::Refresh を使用してすべての関連デュプリカで更新する必要があります。 例えば、次のようにすべてのゲームオブジェクトで MainLoop() が定期的に呼び出されるとします。

Code 18.13 データベースの更新とリフレッシュ
void Sphere::MainLoop() {
    if (IsADuplicationMaster()) {
        // Compute the physics and then update the
        // object’s position.
        Update(m_dsPos);
    } else {
        // Refresh the position.
        Refresh(m_dsPos);
    }
    // Display the object at the correct position.
}

DuplicatedObject::Update または DuplicatedObject::Refresh が呼び出され、カスタム推測航法が実装される場合、 カスタム推測航法モデルとカスタム推測航法モデルポリシーのクラスに実装したさまざまなメソッドが、 次に説明するスキームに従って呼び出されます。

DO マスターでの操作

DuplicatedObject::Update が呼び出されると、次が行われます。

  1. 定義されているモデルポリシークラスの GetRemoteDeadReckoningModel が呼び出され、リモートデュプリカの推測航法モデルのローカルインスタンスを取得します。

    1. モデルが検出されない場合は、更新は送信されません。
    2. この更新ループですでに検出しているモデルを検出する場合、メソッドを再度呼び出すことなく、IsAccurateEnough が以前に呼び出された際に返されたものと同じ結果を返します。
  2. 定義されている推測航法モデルクラスの IsAccurateEnough が呼び出され、 DO マスターのデータセット値をデュプリカ用のモデルと比較します。このメソッドが真を返すと、更新は送信されません。

  3. IsAccurateEnough が偽を返すと、更新は DuplicatedObject::Update で渡された時点で有効なデュプリカに送信されます。

更新が送信されると、次が行われます。

  1. 定義されているモデルポリシークラスの GetRemoteDeadReckoningModel が呼び出され、リモートデュプリカの推測航法モデルのローカルインスタンスを取得します。
  2. 定義されている推測航法モデルクラスの UpdateModelOnMaster が呼び出され、デュプリカの推測航法モデルの DO マスターのローカルインスタンスを更新します。
デュプリカでの操作

デュプリカがそのマスターから更新を受信すると、次が行われます。

  1. 定義されているモデルポリシークラスの GetLocalDeadReckoningModel が呼び出され、推測航法モデルのデュプリカのローカルインスタンスを取得します。
  2. 定義されている推測航法モデルクラスの UpdateModelOnDuplica が呼び出され、推測航法モデルのデュプリカのローカルインスタンスを更新します。

DuplicatedObject::Refresh が呼び出されると、次が行われます。

  1. 定義されているモデルポリシークラスの GetLocalDeadReckoningModel が呼び出され、推測航法モデルのデュプリカのローカルインスタンスを取得します。
  2. 定義されている推測航法モデルクラスの ComputeValue が呼び出され、DuplicatedObject::Refresh が渡された時点で適用可能な推測航法モデルに従って、デュプリカのデータセット値を定義どおりに計算します。