[UE4] Replication Graph

#1. はじめに
　**[Replication Graph](https://docs.unrealengine.com/en-US/Engine/Networking/ReplicationGraph)**は4.20で追加されたNetworkに関するパフォーマンスを改善するための機能の1つです。この機能については、[公式ブログ](https://www.unrealengine.com/ja/tech-blog/replication-graph-overview-and-proper-replication-methods)や[Titchのライブストリーム](https://www.twitch.tv/videos/286656883)でも説明されていますのでそちらもご参考ください。本記事ではReplication Graphの使い方やフレームワークに関する内容について記載しています。
　検証には4.21.1を利用しています。

#2. 概要
　Replication Graphの機能を要約すると以下の通りとなります。

**[主な機能]**
**・Replicationを効率的に行うことでCPUパフォーマンスを改善**
**・ノードグラフは容易に拡張/追加が可能**
**・デバッグ機能やバジェットを調整するための機能/設定が多数**

　これらの詳しい内容に関しては後の章で説明します。ドキュメントに記載されている事項を要約すると、**[Fortnite Battle Royale](https://www.epicgames.com/fortnite/en-US/battle-pass/season-7)**ではReplicationを行う50000体のActorを効率的に処理することでCPUパフォーマンスを抑制しているとあります。50000体のActorのパフォーマンスを改善と切り出すと非常に有用な機能のように思われがちですが、もちろん機能を利用する上での注意点もあります。

**[注意点]**
**・多くのActorを扱う際に効果を発揮します**
**・ノードグラフとは依存関係を持つことを指しBlueprint Nodeのようなものではない**
**・Pluginを有効にするだけではパフォーマンスは良くならない**

<!-- ============================================================ -->
<details><summary>注意点の詳細</summary><div>

---

**・多くのActorを扱う際に効果を発揮します**
　Replication Graphは多数のActorのReplicationを効率的に行うものです。Networkを利用しないケースは当然ながら効果がありません。また、Actorの数が少ない場合は大きなパフォーマンスの改善につながることはないので、単にネットワークのパフォーマンスを考慮する(RPCを多用しない、*NetUpdateFrequency*や*NetCullDistaneSquared*を調整する)だけでも問題ありません。

**・ノードグラフとは依存関係を持つことを指しBlueprint Nodeのようなものではない**
　Replication GraphはNode Graphを組み合わせて構築しますが、Blueprint NodeのようなノードベースのUIが存在するわけではありません。全てのNode GraphはC++でのみ作成、拡張することができます。

**・Pluginを有効にするだけではパフォーマンスは良くならない**
　Replication Graphはカスタマイズすることを前提としているため、プロジェクトにおいて必ずサブクラスを作成して必要なコードを追加する必要があります。単にPluginを有効にするだけでは機能しません。プロジェクトで拡張するにあたっては、サンプルのShooterGameのコードが参考になるため、こちらの理解を深めてから拡張されることをお勧めします。

---

</div></details>

<!-- ============================================================ -->

#3. 使い方
　Replication Graphを有効にして機能を利用するための方法を以下に記載します。

**[使い方]**
**① Pluginを有効にする**
**② ReplicationGraphを継承したカスタムクラスを作成してノードを追加**
**③ ReplicationDriverクラスに作成したカスタムクラスの定義を追加**

<!-- ============================================================ -->
<details><summary>使い方の詳細</summary><div>

---

**① Pluginを有効にする (4.21ではDefaultで無効)**
　EditorのPlugins(もしくは.uprojectファイル)から"Replication Graph"のPluginを有効にします。4.21ではDefaultで無効になっています。

**② ReplicationGraphを継承したカスタムクラスを作成してノードを追加**
　サブクラスとしてUReplicationGraphを継承したクラスを作成します。

```cpp:DefaultEngine.ini
UCLASS(transient, config=Engine)
class UShooterReplicationGraph :public UReplicationGraph
```

**③ ReplicationDriverクラスに作成したカスタムクラスの定義を追加**
　DefaultEngine.iniに②で作成したクラスの定義を追加します。

```cpp:DefaultEngine.ini
[/Script/OnlineSubsystemSteam.SteamNetDriver]
ReplicationDriverClassName="/Script/ShooterGame.ShooterReplicationGraph"
```

---

</div></details>

<!-- ============================================================ -->

#4. フレームワーク
　マルチプレイにおけるEngineの構成とReplication Graphの位置付けをざっくり示すと以下のようになります。
![2018-12-24_00h00_48.png](https://qiita-image-store.s3.amazonaws.com/0/101019/35ffa736-5e92-ddac-e7ae-deafba461393.png)
　Replication GraphのPluginが提供している各オブジェクトの役割について以下に説明します。

##4.1. ReplicationGraph

```cpp:ReplicationGraph
UObject
    UReplicationDriver					// NetDriverと連動する実装を持たないクラス
        UReplicationGraph				// ReplicationGraphの基底クラス
            UBasicReplicationGraph		// 基本的な実装を持つクラス
            UShooterReplicationGraph	// ShooterGameのカスタムクラス
```
　Replication Graphのメイン実装部です。GraphNodeの構築管理、ReplicationやRPCの実行などを処理します。

<!-- ============================================================ -->
<details><summary>UReplicationGraphの概要</summary><div>

---
(※ReplicationGraph.hの内容を和訳したものです)

**Replication Graph**
・Replication Driverの実装です。これはUReplicationGraphをサブクラス化することでカスタマイズできます。デフォルトの実装(UReplicationGraph)は完全には機能せず、オーバーライドして利用することを意図しています。最小限の機能セットで"そのまま使える"最小限の実装についてはBasicReplicationGraph.hをご確認下さい。より高度な実装についてはShooterGame/UShooterReplicationGraphをご確認下さい。


**高度なReplication Graphの概要**
・Graphはネットワーク接続ごとに複製リストを生成するノード群です。基本的に複製するActorの永続的なリスト(Persistent List)を保持してNetwork Connectionに送ります。これにより出来るだけ多くの処理を共有することができ、Actor数×接続数に対するシステムのスケーラビリティが大幅に向上します。

・例えばノードの1つに"Spatialization Node(空間ノード)"があります。距離ベースの関連性を使用する全てのActorは、原則的にこのノードに移動します。そして常に関連性を持つノードもあります。ノードはグローバル/接続毎/共有(例:チームで常に関連するノード)することができます。

・(Replication GrapahがEngineの従来の動作に対して及ぼす)主な影響は、AActor::IsNetRelevantFor()やAActor::GetNetPriority()などの仮想関数がReplication Graphで使用されないことです。その他、いくつかのPropertyについても使用されないか、使用方法が異なります。

・ゲームコードからReplicationのこの部分に関与する方法として、基本的に以下の3つの方法があります。
　　- Graph自身での定義：新しいUReplicationNodesを追加するか、ActorがGraphに配置される方法を変更する
　　- FGlobalActorReplicationInfo：RepGraphが所有する"全体に対してGlobalなActor毎の連想データ"
　　- FConnectionReplicationActorInfo：RepGraphが所有する「接続毎に保存されるActor毎の連想データ"

　Graphから返された後、ActorListは距離と周期についてさらに絞り込まれ、マージされて、優先順位が付けられます。最終的な結果は、Actor Channelを作成/更新するためのロジックを作成するためにソートされたActorのリストです。


**プロジェクトで実装が必要な関数**
　UReplicationGraphのSubClass(カスタムReplication Graph)においては以下の関数を実装する必要があります。

・UReplicationGraph::InitGlobalActorClassSettings
　UReplicationGraph::GlobalActorReplicationInfoMapを初期化します。

・UReplicationGraph::InitGlobalGraphNodes
　CreateNewNodeを介して新しいUGraphNodesをインスタンス化します。
　UReplicationGraph::AddGlobalGraphNodeは全ての接続に対してGlobalな場合に使用します。

・UReplicationGraph::RouteAddNetworkActorToNodes
・UReplicationGraph::RouteRemoveNetworkActorToNodes
　指定のノードに対してActorの登録/破棄を実行します。もしくはノード自身からActorを収集します。

・UReplicationGraph::InitConnectionGraphNodes
　接続毎のノードを初期化します。もしくはAddConnectionGraphNodeを介して共有ノードに関連付けます。

---

</div></details>


<!-- ============================================================ -->
<details><summary>UReplicationGraphのAPI</summary><div>

---

**UReplicationGraph**
コンストラクタです。グローバルデータの生成(FReplicationGraphGlobalData)、グローバル情報Mapデータ(GlobalActorReplicationInfoMap)生成します。

**InitForNetDriver**
ReplicationDriverを初期化します。GlobalActorClassとGlobalGraphNodeの初期化、ClientConnetion(NetConnection)を追加します。NetDriverの初期化のタイミング(UNetDriver::InitBase)で呼び出されます。

**InitNode**
指定のノードを初期化します。UReplicationGraphNodeを初期化して準備リストにノードを登録します。CreateNewNodeで新しいノードを作成した際に呼び出されます。

**InitGlobalGraphNodes**
GlobalGraphNodeを初期化します(基本的にはオーバーライドして必要な処理を書く必要があります)。ReplicationDriver(UReplicationGraph::InitForNetDriver)のタイミングで呼ばれます。

**InitConnectionGraphNodes**
ConnectionManagerの初期化処理、ActorがTearOffした際にハンドル対象を登録しておく必要があります。ConnectionManagerの生成時に呼ばれます。

**AddGlobalGraphNode**
GlobalGraphNodeを追加します。

**AddConnectionGraphNode**
ConnectionManagerにConnectionGraphNodeを追加します。

**RemoveConnectionGraphNode**
ConnectionManagerからConnectionGraphNodeを削除します。

**FindOrAddConnectionManager**
指定のConnectionManagerを検索(無ければ追加登録)します。

**AddClientConnection**
ConnectionList(Connections)に登録します。

**CreateClientConnectionManagerInternal**
新しいConnectionManagerの生成と初期化します。

**RemoveClientConnection**
指定のNetConnectionをConnectionListから削除します。

**SetWorld**
ReplicationGraphのグローバルデータのWorldを登録します。

**InitializeForWorld**
ReplicationGraph上の全てのNodeをリセットし、World上に存在するActorからNetworkActorを再取得します。

**AddNetworkActor**
ActiveNetworkActorsリストに追加してGlobalInfoMapの情報を更新します。

**RouteAddNetworkActorToNodes**
全てのNodeにNetworkActorが追加されたことを通知します。

**RemoveNetworkActor**
ActiveNetworkActorsリストから削除してGlobalInfoMapの情報を更新します。

**RouteRemoveNetworkActorToNodes**
全てのNodeにNetworkActorが破棄されたことを通知します。

**ForceNetUpdate**
Replication情報更新を指定のNetworkActorに通知します。

**FlushNetDormancy**
休止情報更新を指定のNetworkActorに通知します。

**NotifyActorTearOff**
指定のNetworkActorがTearOffされたことをTearOffNodeへ通知します。

**NotifyActorFullyDormantForConnection**
指定のNetworkActorが完全休止したことを通知します。

**NotifyActorDormancyChange**
休止情報が変化したことを通知します。

**ReadyForNextReplication**
次のReplicationの実行可能か結果を返却します。

**ServerReplicateActors**
ServerでのReplicationを処理します。NetworkActorの収集(優先付け、距離/周期のスケーリング、ゲームコードでのスケーリング、ソート)、接続毎のReplicate(PacketBudgetのトラッキング、ActorChannel監視、破棄情報の更新)などを処理します。UNetDriver::TickFlush、UNetDriver::ServerReplicateActorsから呼び出されます。

**ReplicateSingleActor**
Actor単体のReplication処理を実行します。

**HandleStarvedActorList**
欠損したActorリストを更新します。

**UpdateActorChannelCloseFrameNum**
ActorChannelの情報(Actorの欠損タイムアウト検出フレーム)を更新します。

**ProcessRemoteFunction**
RPCの呼び出し処理を実行します。

**IsConnectionReady**
NetConnectionの送信準備が完了しているかの結果を返却します。

---

</div></details>

<!-- ============================================================ -->

##4.2. ReplicationConnectionDriver

```cpp:DebugActor一覧
UObject
    UReplicationConnectionDriver		// 接続毎のReplication拡張機能クラス
        UNetReplicationGraphConnection	// 特定の接続に対するActorReplicate管理クラス
```
　特定の接続に対してActorのReplicationを管理するObjectです。ReplicationConnectionDriverが定義されている場合、ActorChannelが生成される際にReplication専用のConnectionを生成してReplicationを補完します。

<!-- ============================================================ -->
<details><summary>UNetReplicationGraphConnectionのAPI</summary><div>

---

**UNetReplicationGraphConnection**
コンストラクタですがここでは何もしません。

**NotifyActorChannelAdded**
ReplicationActor情報に対象となるActorを追加します。

**NotifyActorChannelRemoved**
ActorChannelが破棄される際に呼び出されます。

**NotifyActorChannelCleanedUp**
ActorChannelがクリーンアップされる際に呼び出されます。内部的に保持しているReplicationActor情報をクリーンアップします。

**InitForGraph**
ReplicationActorに対するReplicationGraph情報を初期設定します。

**InitForConnection**
NetConnectionが持つReplicaitonGraphConnectionを設定し、ReplicationDebugActorを生成します。

**AddConnectionGraphNode**
ReplicationGraphNodeを追加します。

**RemoveConnectionGraphNode**
ReplicationGraphNodeを削除します。

**PrepareForReplication**
Replicationを実行可能かどうかの結果を返します。

**NotifyAddDestructionInfo**
NetDriverでActor情報が破棄される場合に実行されます。PendingDestructInfoListに配置して後から破棄します。

**NotifyRemoveDestructionInfo**
PendingDestructInfoListに設定された情報を破棄します。

**NotifyResetDestructionInfo**
PendingDestructInfoListに設定された情報をリセットします。

**NotifyClientVisibleLevelNamesAdd**
ClientにLevelが追加された際に呼び出します。ActorのDormantOnConnectionを無効にしてレベルにストリーミング情報を通知します。

**ReplicateDestructionInfos**
PendingDestructInfoList(破棄待ち情報)Replicateします。

---

</div></details>

<!-- ============================================================ -->

##4.3. ReplicationGraphNode
```cpp:ReplicationGraphNode一覧
UObject
    UReplicationGraphNode
        UReplicationGraphNode_ActorListFrequencyBuckets			// StreamingLevelに基づくActor管理用
        UReplicationGraphNode_GridSpatialization2D				// 空間分割時のCell管理用
        UReplicationGraphNode_AlwaysRelevant					// AlwaysReleventActor管理用
        UReplicationGraphNode_ActorList							// Actor管理用
            UReplicationGraphNode_ConnectionDormanyNode			// RepListから削除済みDormantActorの管理用
            UReplicationGraphNode_DormancyNode					// DormancyActor管理用
            UReplicationGraphNode_GridCell						// 空間分割時のActor管理用
            UReplicationGraphNode_AlwaysRelevant_ForConnection	// 接続毎のAlwaysReleventActor管理用
            UReplicationGraphNode_TearOff_ForConnection			// 接続毎のTearOffActor管理用
                UShooterReplicationGraphNode_PlayerStateFrequencyLimiter	// (ShooterGame) PlayerStateのRepFreq管理用
                UShooterReplicationGraphNode_AlwaysRelevant_ForConnection	// (ShooterGame) 接続毎のAlwaysReleventActor管理用
```

　ReplicationのグラフノードでReplicationを行う条件をNode毎に設定することができます。

<details><summary>UReplicationGraphNodeのAPI</summary><div>

---

**UReplicationGraphNode**
コンストラクタ、子Nodeに通知するための関数を設定します。

**NotifyAddNetworkActor**
NetworkActorが生成された時、またはActorがReplicationStatusを変更した時に呼び出されます。

**NotifyRemoveNetworkActor**
NetworkActorが破棄された時、またはActorが長い間Replicationを実行しない時に呼び出されます。

**NotifyResetAllNetworkActors**
Worldが変更された時、またはすべてのサブクラスがここに複製されたActorに関する永続的なデータ/リストをDumpするときに呼び出されます (これが呼び出される前に新しい/次のWorldが設定されます)。

**TearDown**
Nodeが破棄される際に実行する処理です。

**GatherActorListsForConnection**
各Nodeで処理すべきActorを収集します。

**PrepareForReplication**
RequiresPrepareForReplicationCall=trueの場合、RootNode(UReplicationGraph::CreateNodeで作成されたNode)のみで、Replicationの前にフレーム毎に1度呼び出されます。

---

</div></details>

<details><summary>その他のGraphNode</summary><div>

**UReplicationGraphNode_ActorListFrequencyBuckets**
ReplicateActorListsを含むノードです。NonStreamingLevelのActor用の複数のバケットが含まれて、交互のフレームで各バケットから引き出されます。広範囲の負荷のバランスをとる方法として利用可能です。

**UReplicationGraphNode_GridSptilization2D**
 マップ上に存在するActorを空間管理するためのベースとなるノードです。空間管理にはワールド上をGridで分割して、2次元座標(X,Y)の情報を持つCellがそれぞれ配置されます。そこで生成されるCellは子ノードとしてUReplicationGraphNode_GridSpatialization2Dが割り当てられます。そしてCell毎に存在しているActorの情報をStatic/Dynamic/Dormancyとして管理します。

**UReplicationGraphNode_AlwaysRelevant**
AlwaysRelevantActorを管理するためのノードです。

**UReplicationGraphNode_ActorList**
Actorの情報を持つ基本ノードです。

**UReplicationGraphNode_ConnectionDormanyNode**
(接続されている)休止中のActorをReplicationListから削除するノードです。

**UReplicationGraphNode_DormancyNode**
MasterActorListの接続毎のコピーを保管します。完全に休止しているConnectionListから要素をSkipして削除します。

**UReplicationGraphNode_GridCell**
　レベル上のActorを空間管理する際のCellノードです。空間分割された数だけこのノードが生成されてActorを管理します。

**UReplicationGraphNode_AlwaysRelevant_ForConnection**
　接続毎にAlwaysRelevantActorを管理します。4.21ではPlayerControllerとViewTarget(通常はpawn)を追加するだけです。

**UReplicationGraphNode_TearOff_ForConnection**
　接続毎にTearOffActorを追加します。4.21ではPlayerControllerとViewTarget(通常はpawn)を追加するだけです。

</div></details>

##4.4. ReplicationGraphDebugActor
```cpp:DebugActor一覧
AActor
  AReplicationGraphDebugActor      // RepGraph関連のデバッグをサポートするActor
```
　Debug用のActorでRepGraphの様々なデバッグ機能を提供します。

#5. ShooterGameのユースケース
　ShooterGameにおけるReplication Graphの位置付けをざっくり示すと以下のようになります。
![2018-12-24_23h45_03.png](https://qiita-image-store.s3.amazonaws.com/0/101019/26758011-dd88-7841-a76b-dff0df2af78c.png)
　全ての機能はUShooterReplicationGraphに記載されていますのでご参考下さい。ノードの構成に関しては基本的に上記から変わりませんが、ノードに所属するActorは動的に変わります。

<!-- ============================================================ -->
<details><summary>ShooterGame の ReplicationGraph</summary><div>

---
(※ShooterReplicationGraph.cppの内容を和訳したものです)

**概要**

　ShooterGameの場合、ReplicationGraphによりActorの関連性が機能する方法が変わります。AActor::IsNetRelevantForはこのシステムでは使用されていません。代わりにUShooterReplicationGraphにはUReplicationGraphNodeが含まれています。これらのノードは、接続毎にReplicateするActorのリストを生成します。これらのリストの殆どはフレームを越えて持続します。これにより、殆どの収集作業(どのActorをReplicaitonの対象と見なすべきか)を共有/再利用することができます。ノードはグローバル(全ての接続で使用される)、接続固有(各接続が独自のノードを取得)、または共有(チームなど、同じチームで共有する全ての接続)のいずれかです。Actorは複数のノードに存在することができます。例えば、PawnがSpatilizationノードにあるだけでなく、AlwaysRelevantノードにある場合もあります。それは同じチームのメンバに2度返却されます。可能であれば最小化する必要がありますがこれは問題ありません。

　"UShooterReplicationGraph"は意図的にゲームコードから使用されないようになっています。これは"ShooterReplicationGraph.h"を他のゲームコードに含める必要はありません。UShooterReplicationGraphはゲームコードに依存し、ゲームコードがブロードキャストするイベント(例:チームに登録/解除するプレイヤーのためのイベント)を登録します。これはUShooterReplicationGraphがActorのReplicationの全体像を把握するためです。一般的なPublic関数を公開するのではなく、ゲーム内のコードが呼び出すことができて全ての通知はUShooterReplicationGraph::InitGlobalActorClassSettingsに明示的に登録されます。


**ShooterGameのノード**
　以下は現在使用されているノードにおける最上位に位置するノードです。

・UReplicationGraphNode_GridSpatialization2D
空間化ノードです。全ての距離基づく関連性を持つActorが登録されます。このノードはマップを2Dグリッドに分割します。グリッド内の各セルには更新/休止状態に基づいてActorのリストを保持する子ノードです。Actorは複数のセルに配置されます。接続はそれらが入っている単一セルから引き出されます。

・UReplicationGraphNode_ActorList
常に関係のあるActorを含むActorListのノードです。これらのActorは常にあらゆる関係に関連しています。

・UShooterReplicationGraphNode_AlwaysRelevant_ForConnection
　接続毎に固有のAlwaysRelevantActorのノードです。このノードは永続リストを維持しませんがフレームごとに構築します。これらのActorは全てPlayerControllerから簡単にアクセスできます。永続リストでは、これらのActorが変更されたときに通知をブロードキャストする必要があります。これは可能ですが現在は不要です。

・UShooterReplicationGraphNode_PlayerStateFrequencyLimiter
　PlayerStateのReplicationを処理するためのカスタムノードです。これは小さなローリングセット(繰り返し実行するため)のPlayerState(2fに1回)をReplicateします。これはPlayerStateが再現するようにするためです。低い安定した周期で接続をシミュレートして共有シリアライズ機能を利用します。AutoProxyなPlayerStateはより高い周期でReplicateされます。
UShooterReplicationGraphNode_AlwaysRelevant_ForConnectionによる所有接続のみ）

・UReplicationGraphNode_TearOff_ForConnection
TearOffするActorを処理するための接続毎の固有のノードです。これはReplication Graphの基本実装で作成および管理されます。


**従属Actor(AShooterWeapon)**
　Replication Graphは、依存するActorのReplicationの概念を導入します。これは別のActorがReplicateする時にのみReplicateするActor(AShooterWeapon)です。つまり武器のActor自体は決してReplicationGraphに入りません。それは自分自身で収集することもなく、優先順位が付けられることもありません。PawnがReplicateしたときに複製する機会があるだけです。武器のActorのために特別な作業をする必要がないのでグラフをより小さくします。UShooterReplicationGraph::OnCharacterWeaponChangeを参照してください。これはActorが依存するActorリストに追加または削除される方法です。


**使い方**
・何か必要な場合は避けてください
必要な場合はクラスデフォルトでAActor::bAlwaysRelevant=trueを設定するだけで問題ありません。

・常に接続に関連するものにする
UShooterReplicationGraphNode_AlwaysRelevant_ForConnection::GatherActorListsForConnectionを変更する必要があります。これはActorが他のノードの1つに入れられないようにするためです。これを行う最も安全な方法は、UShooterReplicationGraph::InitGlobalActorClassSettingsでEClassRepNodeMappingをNotRoutedに設定することです。


**デバッグ方法**
　問題がシステム固有のものか、もしくは一般的なReplicaitonやGamePlayの問題であるかを確認するにはReplicaiton Graphを無効にすることをお勧めします。問題がReplication Graph関連であれば、利用可能なコンソールコマンドがあります。ReplicationGraph_Debugging.cppをご覧ください。ClientからServer上で実行するには"Cheat"コマンドを使用してください。

・Net.RepGraph.PrintGraph
グラフをログに出力します(ノードと所属するActor)。

・Net.RepGraph.PrintGraph class
上記と同じですがクラスごとにグループ化されます。

・Net.RepGraph.PrintGraph nclass
上記と同じですがネイティブクラスでグループ化されます(Blueprintのノイズを隠します)。

・Net.RepGraph.PrintAll [Frames] [ConnectionIdx] ["Class"/"Nclass"]
グラフ全体、収集したActor、x個のフレームに対して与えられた接続に対してそれらがどのように優先されたかを表示します。

・Net.RepGraph.PrintAllActorInfo [ActorMatchString]
Actor/Classに関連付けられているクラス、グローバル、および接続毎のReplication情報を出力します。MatchStringが空の場合、全ての情報が出力されます。クライアントから直接呼び出します。

・ShooterRepGraph.PrintRouting
各クラスのEClassRepNodeMappingを出力します。特定のActorがReplicaiton Graphでどのように接続されるか(またはルーティングされないか)です。

---

</div></details>

<!-- ============================================================ -->

<!-- ============================================================ -->
<details><summary>ShooterGame の ReplicationGraphDebug</summary><div>

---

**ShooterRepGraph.DestructInfo.MaxDist (30000.f)**
FActorDestructionInfoとReplicateするConnectionとの間の最大距離を上書きします。実際の値はこの値の2乗の値が適用されます。

**ShooterRepGraph.DisplayClientLevelStreaming (0)**
有効な場合、レベルに追加されたActorの情報をログに出力します。

**ShooterRepGraph.CellSize (10000.f)**
UReplicationGraphNode_GridSpatialization2DのCellSizeを設定します。この値が空間分割におけるCellのXYの大きさとなります。

**ShooterRepGraph.SpatialBiasX (-150000.f)**
基本的に"Min X"はReplicate用の初期値です。 Actorがこの外に出現するとシステムは自動的にリセットされます。

**ShooterRepGraph.SpatialBiasY (-200000.f)**
基本的に"Min Y"はReplicate用の初期値です。Actorがこの外に出現するとシステムは自動的にリセットされます。

**ShooterRepGraph.DynamicActorFrequencyBuckets (3)**
動的に空間的なActorを広めるBuket数を定義します。これは個々のActorが独自のNetUpdateFrequencyチェックを行う前に発生します。

**ShooterRepGraph.DisableSpatialRebuilds (1)**
この値が有効な場合、すべての空間の再構築(SpatilRebuildBlacklist)を無効にします。

---

</div></details>

<!-- ============================================================ -->

#6. Console Command
Replication Graphで提供されるConsole Commandについて以下に示します。

**Net.RepGraph.DrawGraph**
GraphNodeの構造をHUDに出力します。
![2018-12-19_00h22_07.png](https://qiita-image-store.s3.amazonaws.com/0/101019/4528fc02-6488-a6ea-ea5b-fe5261305ddc.png)

**Net.RepGraph.PrintGraph**
GraphNodeの構造をログに出力します。
![2018-12-19_00h24_18.png](https://qiita-image-store.s3.amazonaws.com/0/101019/28cc9cf7-a1a9-e3e8-8522-d1fa374f9b94.png)


<!-- ============================================================ -->
<details><summary>その他のコンソールコマンド</summary><div>

---
(※全てを実証していませんがおおよそこの通りです)

**Net.RepGraph.Pause (0)**
ReplicationGraphのActorReplicationを中断します。

**Net.RepGraph.Frequency (0.00f)**
ReplicationManagerが有効な場合、Replicationの周期を指定します。0の場合はレガシーなNetDriverの実装を使用します。

**Net.RepGraph.UseLegacyBudget (1)**
レガシー実装におけるバジェットを指定します。

**Net.RepGraph.FixedBudget (0)**
固定されたバジェットを指定します(Bits/frame)。

**Net.RepGraph.SkipDistanceCull (0)**
有効な場合、ReplicationGraphにおけるNetworkDistanceCullingをスキップします。

**Net.RepGraph.PrintCulledOnConnectionClasses (0)**
有効な場合、カリングされたConnectionClassを出力します。

**Net.RepGraph.PrioritizedLists.Print [ConnectionIdx]**
![2018-12-19_00h25_16.png](https://qiita-image-store.s3.amazonaws.com/0/101019/9b057595-c1e3-8824-bf4f-f5794766e564.png)

**Net.RepGraph.TrackClassReplication (0)**
有効な場合、ClassのReplicationをトラッキングします。

**Net.RepGraph.PrintTrackClassReplication (0)**
有効な場合、ClassのReplicationトラッキング結果を出力します。

**Net.RepGraph.Verify (0)**
有効な場合、ActorがNodeに追加された際にActorの検証を実行します(処理速度が低速なためデフォルトはOFFとなっています)。

**Net.RepGraph.TrickleDistCullOnDormanyNodes (1)**
有効な場合、距離CullingされたDormancyノードに所属するActorはDormancyノードをリセットします。

**Net.RepGraph.EnableRPCSendPolicy (1)**
有効な場合、RPC送信ポリシーを有効にします(例:特定の関数をキューに入れるのではなく即時送信します)。

**Net.RepGraph.LogNetDormancyDetails (0)**
有効な場合、Replication Graph/Nodeの処理におけるDormancy情報の詳細ログを出力します。

**Net.RepGraph.LogActorRemove (0)**
有効な場合、Replication Graph/NodeからActorが削除されたことをログ出力します。

**Net.RepGraph.LogActorAdd (0)**
有効な場合、Replication Graph/NodeにActorが追加されたことをログ出力します。

**Net.RepGraph.Lists.DisplayDebug**
RepActorListのstatsをHUDに出力します。
![2018-12-23_18h03_46.png](https://qiita-image-store.s3.amazonaws.com/0/101019/60dddc37-0f5c-c4f9-a8b7-6258fd621634.png)

**Net.RepGraph.PrintAllActorInfo [MatchString]**
MatchStringを含むパス名を持つActorに関するグローバルおよび接続固有の情報を出力します。クライアントから呼び出すことができます。

**Net.RepGraph.PrioritizedLists.Print [ConnectionIdx]**
優先順位付けされたReplicationListを出力してログに出力します。
![2018-12-23_18h05_17.png](https://qiita-image-store.s3.amazonaws.com/0/101019/41d6456b-0751-893a-c4ab-55a367b315ab.png)

**Net.RepGraph.PrioritizedLists.Draw [ConnectionIdx]**
HUD上の優先順位付きReplicationListを描画します。
![2018-12-23_18h08_51.png](https://qiita-image-store.s3.amazonaws.com/0/101019/6d9cd74d-909a-afa8-7a3d-792cda76d520.png)

**Net.RepGraph.PrintAll [Frames] [ConnectionIdx] ["Class"/"Num"]**
指定されたFramesに対して、指定されたConnectionIdxのレプリケーショングラフと優先順位付きリストを出力します。

**Net.PacketBudget.HUD**
Packet Budgetの詳細をHUDに出力します。

**Net.PacketBudget.HUD.Toggle**
Packet Budgetの詳細をHUDに出力する際の停止/更新を切り替えます。

**Net.RepGraph.Lists.Details**
拡張されたRepActorListの詳細をログに出力します。

**Net.RepGraph.StarvedList [ConnectionIdx]**
ActorのStarvedListをHUDに出力します。

**Net.RepGraph.Lists.Stats**
RepActorListのstatsをログに出力します。
![2018-12-23_18h10_52.png](https://qiita-image-store.s3.amazonaws.com/0/101019/0e9a5414-3ecd-8543-e6cd-05d8973c57d8.png)

---

</div></details>

<!-- ============================================================ -->

#7. まとめ
　ReplicationGraphは、Replicationを効率的に管理できて通信コストを削減するのに役立ち、Replicationの管理状況が把握しやすいという面でのメリットがあります。しかしながら、ゲームに併せて適切に設定・拡張しないと不都合が発生する可能性もあるという点や、ReplicateするActorが少ない場合はパフォーマンス改善の効果が大きくありません。よって、この機能を利用する際には、コンテンツに適合するかどうかを予め検討した上で、コンテンツとReplicationGraphで実現する内容を良く把握した上でご利用下さい。