BLOGブログ

2025.04.02UE5UE/ C++UE/ Network

[UE5] ReplicationGraphを組んで、同期内容を絞る

執筆バージョン: Unreal Engine 5.5.4

 

こんにちは。エンタープライズエンジニアの方井です。

本日はReplicationGraphを組んでみようと思います。

 

ReplicationGraphとはなんでしょうか。公式では以下のページに詳しくまとまっております。

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

一番上の概要はかなりよくまとまっているためこれ以上簡単に説明できるかは難しいですが簡単に言うと、
「全部のActorに対して毎回同期するかチェックするのは大変だから、グラフ構造にしてチェックを飛ばすグループを作ったり処理を単純化して負荷を軽減しよう」
という話になります。ここでいうグラフとはBlueprintエディタやMaterialエディタ等の処理のグラフではなく、データ構造的な意味合いのグラフです。この機能を活用することで負荷軽減が行えることはもちろん、Replicationしないことで何かを隠す(非表示にする)ことの代替にもなります(それが必要な場面は分かりませんが…)。

それでは実際にReplicationGraphを組んで、自分だけの同期内容を作成しましょう。


 

1. 新規プロジェクト作成

UE5.5の新規プロジェクト作成画面

リスポーン地点のような安心感。新規プロジェクト作成画面です。実験の分かりやすさを優先してThirdPersonTemplateを選びます。また、Replicationの処理を記述するため、C++で作成します。

 

2. 独自のReplicationGraphノードを作成する

UReplicationGraphNode_ActorListを継承するクラスをC++で作成します。そして、以下のように編集します。

ソースファイルは以下のような形です。

内容を簡単に言えばこのノードに振り分けられたActorについて、AbilitySystemComponent内に特定のTag(ReplicationGraphTest.State.Invisible)があればほかの人に同期しないというものになります。

 

3. 独自のReplicationGraphを作成する

続いて、グラフを作成していきます。ここで作業簡略化のためにエンジンに同梱されているUBaseReplicationGraphという標準的な機能が実装され終わっているクラスを継承して、独自部分だけを作成出来たら良かったのですが、そのクラスにはAPIマクロが付与されておらず外部モジュールから利用することはできませんでした。そのため、UBaseReplicationGraphの実装をそのまま頂きつつ、独自の実装も盛り込んだUReplicationGraphを継承するクラスをC++で作成します。そして、以下のように編集します。

ソースファイルは以下のような形です。UBaseReplicationGraphの実装をそのまま書くのは規約に反するため、コメントアウトを参考に以下リンクから導入してください。

UE5.5.3 BasicReplicationGraph.cpp

基本的には、ACharacter継承のものだけを独自ノードに入れ、他はBaseReplicationGraphと同様にルールに従って振り分けております。つまり、ACharacter継承かつAbilitySystemで特定のTagを持った場合は、他人にReplicateされることなくなりました。

 

4. 独自のReplicationGraphを使用する

作成したReplicationGraphを使用するよう、Engineへ伝えましょう。今回は特定のGameModeの際に動くようにしたいと思います。プロジェクト作成時に同時に作成されたGameModeのC++コンストラクタに以下のように追記します。

 

5. (Optional)アビリティ発動時のエフェクトを作成する

Optional、つまりやらなくても特に問題無い作業です。

「AbilitySystemで特定のTagを持った場合」というグラフを組んだ通り、AbilitySystemを使用します。発動時、何も画面に反映されていないと不安なのでそれが分かるエフェクトActorを作成します。

Actorを作成してNiagaraParticleSystemComponentを追加し、そこにEngine組み込みのアセットであるFountainLightweightを設定します。また、Replicates設定をONにし、同期できるようにします。

Niagaraを出すだけのActor

 

6. Invisibleアビリティを作成する

「AbilitySystemで特定のTagを持った場合」というグラフを組んだ通り、Invisibleアビリティ発動でTagを付与しようと思います。また、このアビリティは時限式で解除されるようにします。

はじめに、GameplayAbilityを親クラスにBlueprintアセットを作成します。そして、ActivateAbilityイベントで呼ばれる処理を記述します。Authorityがあれば先ほど作成したエフェクトをSpawnし、一定時間後(InvisibleTime)にアビリティが終了されるようにします。

ActivateAbility時に呼ばれる処理

また、アビリティ終了時に呼ばれるイベントに、先ほどSpawnしたエフェクトを破棄する処理を追加します。

EndAbility時に呼ばれる処理

アビリティの設定を行います。まず、TriggersにあるAbilityTriggersはReplicationGraphTest.Action.Invisibleを追加して、このTagがActivateされたときにアビリティが発動するようにします。
次に、TagsにあるAssetTagsは同様にReplicationGraphTest.Action.Invisibleを追加し、ActivationOwnedTagsにReplicationGraphTest.State.Invisibleを追加します。これにより、アビリティ発動中はOwnerに対してReplicationGraphTest.State.Invisible付与されることになります。ReplicationGraphで書いた条件と同じですね!

GameplayAbilityアセットの各種設定

 

7. Test用Characterを作成する

「AbilitySystemで特定のTagを持った場合」というグラフを組んだ通り、アビリティを発動してReplication対象から外れるようなPlayerCharacterを作成します。

BP_ThirdPersonCharacterを継承したCharacterクラスを作成します。そして、アビリティを扱えるようComponentsにAbilitySystemComponentを追加します。

AbilitySystemを追加する

次に、作成したInvisibleアビリティをAbilitySystemに与えるため、BeginPlayからGiveAbilityノードを呼びます。

アビリティを追加する

最後に、0キーを押すことでアビリティを発動するようにします。サーバー側で発動してほしいため、Remoteだった場合はRunOnServerイベントへ飛ぶようにし、TryActivateAbilitiesByTag関数で発動トリガーであるReplicationGraphTest.Action.Invisibleを呼びます。

0キーを押したらアビリティを発動する

 

8. Test用GameModeを作成する

ReplicationGraphを使用する処理をC++側のGameModeに記述したため、それを継承してPlayerCharacterの設定を行います。

プロジェクト作成時に同時に作成されたGameModeを継承したGameModeアセットを作成し、DefaultPawnClassを先ほど作成したCharacterアセットに変更します。
そして、テストするレベルのWorldSettingsのGameModeOverrideに設定して、このGameModeが使用されるようにします。

GameModeをレベルに設定する

 

9. 試す

DedicatedServer設定でClientを2つ用意し、実際に動かしてみましょう。

通常は位置が正しく同期されていますが、0キーを押してInvisible状態になるとほかのプレイヤーからは見えなくなります。Invisible状態が解除されると再び同期され、正しく表示されます。Invisible状態かどうかはエフェクトが表示されているかどうかでわかりますね。

見事、ReplicationGraphに独自のノードを埋め込み、動的にReplication可否を切り替えて同期内容を変更することができました!!データが同期されていないということはClient側へのパケットにもRAMにも載っていないため、どう頑張っても相手の位置を特定することはできません。不正防止の観点からも使えるテクニックかもしれません。

 

以上で、デモの説明は終了です。
それでは、良いReplication生活を!!