レプリケーション グラフ

レプリケーション グラフの機能とレプリケーション グラフ ノードの概要。

レプリケーション グラフ プラグインは、マルチプレイヤー ゲームにおけるネットワーク レプリケーションのためのシステムです。これは、多数のプレイヤーとレプリケートされたアクタに対応できるように設計されています。 例えば、Epic の Fortnite Battle Royale では、100 人のプレイヤーと接続して約 50,000 個のレプリケートされたアクタとのゲームが可能です。 標準的なネットワークのレプリケート方法は、接続されている各クライアントに更新を送信するかどうかを各レプリケート アクタに決定させるというものですが、これはマルチプレイヤー ゲームのような場合にはうまく機能せず、サーバーの CPU 計算処理のボトルネックとなります。 アクタを段階的なグループに分割したり、単に更新頻度を下げたりすると問題が軽減される可能性がありますが、更新頻度が低下するためクライアントの操作性も低下します。 しかし、レプリケーション グラフを使用すると、アクタが接続されている各クライアントを個別に評価する必要がなくなり、クライアントの操作性を犠牲にすることなく CPU の処理が重くなる問題を解決できます。

構造

レプリケーション グラフ には一連のレプリケーション グラフ ノードが含まれています。これらのノードは、要求に応じて各クライアントにレプリケートするアクタのリストをビルドします。 このシステムは、単なるレプリケートされたアクタ自身によって処理される関数呼び出しではなく、永続的なオブジェクトからビルドされているため、データは複数のフレームにわたって保存され、クライアント接続間で共有されます。 この永続的な共有データにより、レプリケーション グラフ システムが各クライアントのレプリケート リストを作成するのにかかる時間を短縮できます。

レプリケーション グラフ ノード (略して「ノード」と呼びます) は、どのアクタが更新を必要とする可能性があるかを確定し、それらをグループに分類し、クライアントに送信する事前計算されたリストを格納するなどの実際の作業を行います。 究極の目的は、各クライアント接続にアクタの「レプリケート リスト」をオンデマンドで提供することです。これにより、サーバーは 1 クライアントあたり、アクタあたりの CPU サイクルをできるだけ少なくできます。 各ノードは独自の方法で機能させることができるので、必要に応じて自分のゲーム用のカスタム ノードを書くことをお勧めします。 ノードはゲームに依存しないものでも、ゲーム固有の情報を利用するものでもかまいません。 ゲーム内での役割に基づいてアクタをさまざまなノードに配置すると、レプリケートの方法とタイミングをより適切に制御できるようになります。 ゲーム内での動作に基づき可能な限り最良のノードにアクタを割り当てるため、新しいノードをビルドしてレプリケーション グラフを使用すると、ネットワーク レプリケーション リストの作成にかかる CPU の処理時間を大幅に短縮できます。

システムを有効にする

次の 2 つの方法のいずれかで、カスタム レプリケーション ドライバ (レプリケーション グラフの親クラス) を使用するようにプロジェクトを構成できます。

  • 「DefaultEngine.ini」ファイルでレプリケーション ドライバ クラスを指定します。

  • レプリケーション ドライバ クラスのインスタンスを返す関数を、デフォルトのレプリケーション ドライバの作成デリゲートにバインドします。

「ShooterGame」プロジェクトは、レプリケーション グラフの設定方法と実装方法の良い例となります。 ただし、レプリケーション グラフは分割スクリーンのゲームでは現在機能しないため、コンソール ビルドでは無効になっています。

コンフィギュレーション (.ini) ファイル

エンジンのデフォルトのレプリケーション ドライバを設定するには、プロジェクトの 「DefaultEngine.ini」ファイルを開きます。 [/Script/OnlineSubsystemUtils.IpNetDriver] セクションを検索 (または追加) し、使用するレプリケーション ドライバ (またはレプリケーション グラフ) クラスの名前がわかるように「ReplicationDriverClassName」エントリを設定 (または追加) します。 これはおおよそ下記のようになります。下記では、「ProjectName」を実際のプロジェクトの名前に置き換え、「ClassName」をカスタム クラスの名前に置き換えます。

[/Script/OnlineSubsystemUtils.IpNetDriver]
ReplicationDriverClassName="/Script/ProjectName.ClassName"

コードでバインドする

プロジェクトにネットワーク要件が大きく異なる複数のゲームモードまたはマップがある場合、デリゲートにバインドすると、現在のゲームモードまたはコードでマップするための適切なレプリケーション ドライバを作成できます。 このメソッドを使用するには、CreateReplicationDriverDelegate という名前の UReplicationDriver 関数に関数をバインドします。 このサンプルのラムダ関数のように、バインドされた関数は目的のレプリケーション ドライバ クラスの有効なインスタンスを返す必要があります。

    UReplicationDriver::CreateReplicationDriverDelegate().BindLambda([](UNetDriver* ForNetDriver, const FURL& URL, UWorld* World) -> UReplicationDriver*
    {
    return NewObject<UMyReplicationDriverClass>(GetTransientPackage());
    });

発展的な例

多数の接続されたクライアントとさらに多数の同期されたアクタを持つゲームでは、レプリケーション グラフがタイプとステータスに基づいてアクタを異なるノードに割り当てます。それにより、CPU 処理時間を大幅に短縮できます。 これにより、従来のレプリケート方法では実現不可能だったゲームをビルドできるようになりました。 概念レベルでは、この規模のゲームは大量のレプリケートされたアクタと接続されたクライアントを処理するために、以下の機能を備えたレプリケーション グラフとレプリケーション グラフ ノードをビルドできます。

  • 場所に基づいたアクタのグループ分けを行います。 バトルロイヤル、MOBA、MMORPG といったジャンルのゲーム、ダンジョンクローラーまたは一人称/三人称視点のシューティング ゲーム用の事前定義済みの部屋またはゾーン、もしくはゲームのプレイ空間に合った方法で、ワールドをグリッド空間に分割することができます。 ノードがクライアントのカメラが存在するグリッドセルまたは部屋に関係なく永続的なアクタのリストをクライアントに提供するだけなので、そのアクタを参照する可能性のあるグリッドセルまたは部屋にアクタを追加すると、クライアントの更新が速くなります。

  • 「dormant (ドーマント/休眠状態)」に配置されたアクタを識別し、それらを別のリストに入れます。 プレイヤーや AI でコントロールされたキャラクターといったような、頻繁に更新を要求されるかもしれないアクタがある一方で、レベル内にあらかじめ配置されていて、プレイヤーが操作するまでは自分自身で移動したり状態を変更したりしないアクタも多くあります。 これらのアクタは、 (おそらくゲームセッション全体といったような) ネットワークの更新情報を長期間送信する必要がないこともあります 。 例えば、「Fortnite Battle Royale」では、プレイヤーとプロジェクタイルはゲームから除外されるまで絶えず更新され続けます。 一方、ツリーは長期間ドーマント状態にあり、どのクライアントにも更新を要求しません。 ツリーにダメージがあった時に、ツリーを確認できるクライアントがそのダメージを受けたという更新情報を受け取る必要があります。 そして、ツリーが破壊され、その情報を受信したクライアントは、ツリーに関するそれ以上の更新を受信する必要がなくなります。

  • ゲーム内のキャラクターが アイテムを拾って持ち運ぶことができる場合、それらのアイテムをキャリアで更新します。 プレイヤーがアイテムや武器を引き出して持ち運ぶ場合、あるいは衣服や鎧を着た場合、それらアイテムを表すアクタ (単なるコンポーネントではなく、別のアクタであると仮定します) を特別なグループに追加します。そのグループでは、それらアクタを所有するプレイヤーが更新された時に、それらアクタも常に更新されるようになり、それ以外の場合は更新しなくなります。

  • 常にすべてのクライアントに認知される特別なアクタのリストを作ります。 すべてのプレイヤーに対して常にネットワーク上関連のある特別なアクタです。これらのアクタを追跡する単純なノードに入れることができます。これにより、無駄な CPU 計算を行っている可能性のある他のリストから除外できます。

  • 特定のクライアントに常に関連する (または関連しない) 特別なアクタのリストを作成します。 同様の常に関連性のあるリストのノードは、個々のプレイヤー、またはプレイヤーのチームに対して作成することができます。 これは、プレイヤーのチームメイトが確実に常時更新されていること、またはゲーム固有の特殊な対戦相手を検出する能力によって「発見」された対戦相手を、発見したプレイヤーのチーム全体へその対戦相手を見えるようにしたい際に、特に便利です。 その発見に関する情報の期限が切れた場合は、これらのアクタをデフォルトのノードに戻すことができます。

ゲーム内でのアクタの役割に関する知識に基づいてアクタをさまざまなノードに賢く割り当てるレプリケーション グラフをビルドすると、サーバーの CPU 処理時間を最大限短縮できます。 その結果、他の方法では現在のハードウェアでは実行できなかったゲームのサーバー パフォーマンスを安定させることができます。 レプリケーション グラフ プラグインには、大規模オンラインゲームで使用できるレプリケーション グラフ ノード クラスがいくつかあります。 特定のゲームの内部動作の知識に基づいて、カスタム ノード クラスをビルドすることもおすすめです。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル