ue-networking-replication について
Unreal Engine 5.8 開発者向けのネットワーク・レプリケーションスキルです。サーバー権限、プロパティや RPC、Fast Array、Push Model、追加のレプリケーションシステムを解説します。
主な機能
- 01ネットワークロールと権限判定
- 02プロパティ複製とライフタイム条件
- 03Push Model のダーティーマーク
- 04Fast Array の差分シリアライズ
- 05Server、Client、Multicast RPC
- 06Iris と Replication Graph
活用シーン
- 01Actor のプロパティと移動状態の複製
- 02接続ごとのプロパティ配信制御
- 03更新されるインベントリ配列の複製
- 04RPC 種別の選択とサーバー呼び出し設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ quodsoler/ unreal-engine-skills --skill ue-networking-replicationインストール後、Claude Code で/ue-networking-replicationを入力して読み込まれたか確認します。
同梱ファイルreferences/replication-patterns.mdreferences/rpc-decision-guide.md
詳細
UE ネットワークとレプリケーション
対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーで確認済みです。古い形式は「非推奨 — 使用しないでください」に記載しています。
アクター、コンポーネント、サブオブジェクト向けのサーバー権威型レプリケーションです。コア API は Engine モジュール(GameFramework/Actor.h、Engine/NetDriver.h、Net/UnrealNetwork.h)と NetCore モジュール(Net/Core/PushModel/PushModel.h、Net/Serialization/FastArraySerializer.h)にあります。ELifetimeCondition と REPNOTIFY_* は CoreUObject(UObject/CoreNetTypes.h)にあります。オプションのシステムとして、Iris レプリケーションシステム(IrisCore モジュール、Build.cs の SetupIrisSupport(Target))と ReplicationGraph プラグイン(5.8 ではベータ版、Build.cs のモジュール ReplicationGraph)があります。
コンテキスト
.agents/ue-project-context.md が存在する場合は読み込んでください(モジュール名、規約、有効なプラグイン、GAS/ネットワーク設定)。ファイルがなくても作業を中断しないでください。
リクエストとコードベースから該当する分野を特定してください。解釈が 2 通り考えられ、それぞれで異なるコードになる場合にのみ質問してください。
| リクエストの内容… | 参照先 |
|---|---|
| 権限チェック、ロール、専用サーバーとリッスンサーバー | ネットロール、ネットモード、権限 |
変数のレプリケーション、OnRep_、GetLifetimeReplicatedProps | プロパティのレプリケーション |
プロパティを受信する対象(COND_*) | ライフタイム条件 |
| フレームごとの比較コストの削減 | プッシュモデル |
| レプリケーションされる配列/インベントリ | 高速配列シリアライズ |
| サーバー/クライアント/マルチキャスト呼び出し、検証 | リモートプロシージャコール |
SetOwner、関連性、カリング、休止状態 | 所有権、関連性、休止状態 |
アクターまたはコンポーネントが所有する UObject のレプリケーション | サブオブジェクトのレプリケーション |
| シミュレートされたボディ、物理予測 | 物理レプリケーション |
Iris、net.Iris.UseIrisReplication | Iris レプリケーションシステム |
| 50 以上の接続、空間的な関連性 | ReplicationGraph |
UNetDriver、UNetConnection、切断の検出 | ネットドライバーと接続 |
一連の手順を示す例については、レプリケーションパターンを参照してください。RPC の選択表と、エンジンの RPC 宣言をそのまま掲載したものについては、RPC 判断ガイドを参照してください。
ネットロール、ネットモード、権限
ENetRole は Engine/Classes/Engine/EngineTypes.h で宣言されています。アクセサーは AActor にあります。
ROLE_None // not replicated
ROLE_SimulatedProxy // remote copy driven by replicated state
ROLE_AutonomousProxy // remote copy of the locally controlled pawn/controller
ROLE_Authority // owns and may mutate this actor
GameFramework/Actor.h より:
ENetRole GetLocalRole() const;
ENetRole GetRemoteRole() const;
bool HasAuthority() const;
ENetMode GetNetMode() const;
bool IsNetMode(ENetMode Mode) const;
ENetMode(Engine/Classes/Engine/EngineBaseTypes.h):NM_Standalone、NM_DedicatedServer、NM_ListenServer、NM_Client。NM_Client より前のすべてのモードはサーバーです。
| マシン | GetLocalRole() | GetRemoteRole() |
|---|---|---|
| サーバー | ROLE_Authority | ROLE_AutonomousProxy または ROLE_SimulatedProxy |
| 所有クライアント | ROLE_AutonomousProxy | ROLE_Authority |
| その他のクライアント | ROLE_SimulatedProxy | ROLE_Authority |
リッスンサーバーでは、ホストは ROLE_Authority であり、同時にローカル制御されています。ホスト専用またはクライアント専用の処理をスキップするには、APawn::IsLocallyControlled() を使用してください。
プロパティのレプリケーション
// MyReplicatedActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyReplicatedActor.generated.h"
UCLASS()
class MYGAME_API AMyReplicatedActor : public AActor
{
GENERATED_BODY()
public:
AMyReplicatedActor();
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
protected:
UPROPERTY(ReplicatedUsing = OnRep_Health)
float Health = 100.f;
UPROPERTY(Replicated)
int32 TeamId = 0;
UFUNCTION()
void OnRep_Health(float PreviousHealth);
};
// MyReplicatedActor.cpp
#include "MyReplicatedActor.h"
#include "Net/UnrealNetwork.h"
AMyReplicatedActor::AMyReplicatedActor()
{
bReplicates = true; // or SetReplicates(true) at runtime
SetReplicateMovement(true);
SetNetUpdateFrequency(10.f); // replication considerations per second
SetMinNetUpdateFrequency(2.f); // throttled floor when nothing changes
SetNetCullDistanceSquared(225000000.f); // 150 m squared
NetPriority = 1.f; // still a public field in 5.8
}
void AMyReplicatedActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps); // never omit
DOREPLIFETIME(AMyReplicatedActor, Health);
DOREPLIFETIME_CONDITION(AMyReplicatedActor, TeamId, COND_InitialOnly);
}
void AMyReplicatedActor::OnRep_Health(float PreviousHealth)
{
// Clients only. Must be idempotent: relevancy changes re-fire it.
}
ルール:
OnRep_はUFUNCTION()でなければなりません。省略可能な単一のパラメーターは変更前の値で、プロパティの型と一致している必要があります。- レプリケートされるプロパティを書き込めるのはオーソリティのみです。変更を行ったマシンでは
OnRep_は呼び出されません。 - レプリケートされた構造体内の
UPROPERTY(NotReplicated)は、そのメンバーを除外します。 FVector_NetQuantize/_NetQuantize10/_NetQuantize100/_NetQuantizeNormal(Engine/NetSerialization.h)は、ワールド位置の帯域幅を削減します。小数点以下 0 桁、1 桁、2 桁、および法線の成分あたり 16 ビットです。FRepMovement(Engine/Classes/Engine/ReplicatedState.h)は、SetReplicateMovement(true)の場合に位置/回転/速度を保持します。後処理するにはvirtual void OnRep_ReplicatedMovement()をオーバーライドします。UCharacterMovementComponentは移動を独自にレプリケートします。ue-character-movementを参照してください。- 接続に対する最初のバンチでは、対象となるすべてのプロパティが一度に送信されます。初期状態は小さく保ち、スポーン時のみのデータは
COND_InitialOnlyの対象にしてください。
マクロ(Net/UnrealNetwork.h):DOREPLIFETIME、DOREPLIFETIME_CONDITION、DOREPLIFETIME_CONDITION_NOTIFY、DOREPLIFETIME_WITH_PARAMS、DOREPLIFETIME_WITH_PARAMS_FAST、DOREPLIFETIME_WITH_PARAMS_FAST_STATIC_ARRAY、DOREPLIFETIME_ACTIVE_OVERRIDE、DOREPLIFETIME_ACTIVE_OVERRIDE_FAST、DISABLE_REPLICATED_PROPERTY。
FDoRepLifetimeParams(Net/UnrealNetwork.h)は、_WITH_PARAMS 形式の基となる構造体です。
ELifetimeCondition Condition = COND_None;
ELifetimeRepNotifyCondition RepNotifyCondition = REPNOTIFY_OnChanged; // or REPNOTIFY_Always
bool bIsPushBased = false;
ライフタイム条件
CoreUObject/Public/UObject/CoreNetTypes.h にある ELifetimeCondition 列挙型の全項目:
| 値 | 送信先 |
|---|---|
COND_None | すべての接続 |
COND_InitialOnly | 最初のバンチのみ |
COND_OwnerOnly | アクターを所有する接続 |
COND_SkipOwner | オーナー以外のすべて |
COND_SimulatedOnly | アクターがシミュレートプロキシである接続 |
COND_AutonomousOnly | アクターが自律プロキシである接続 |
COND_SimulatedOrPhysics | シミュレートプロキシ、または bRepPhysics アクター |
COND_InitialOrOwner | 最初のバンチ、またはオーナー |
COND_Custom | 常に対象。アクティブオーバーライドマクロを使用して実行時に切り替えます |
COND_ReplayOrOwner | リプレイ接続、またはオーナー |
COND_ReplayOnly | リプレイ接続のみ |
COND_SimulatedOnlyNoReplay | シミュレートプロキシ。ただしリプレイを除く |
COND_SimulatedOrPhysicsNoReplay | シミュレートプロキシ、または bRepPhysics。ただしリプレイを除く |
COND_SkipReplay | リプレイ接続以外のすべて |
COND_Dynamic | 条件は実行時にオーバーライドされます。設定するまではレプリケートされます |
COND_Never | レプリケートされません |
COND_NetGroup | サブオブジェクトのみ — 同じネット条件グループ内の接続 |
COND_NetGroup は、UNetworkSubsystem::GetNetConditionGroupManager()(Net/Subsystems/NetworkSubsystem.h)経由で取得する UE::Net::FNetConditionGroupManager(Net/Core/Misc/NetConditionGroupManager.h、モジュール NetCore)と組み合わせて使用します。
#include "Net/Core/Misc/NetConditionGroupManager.h"
#include "Net/Subsystems/NetworkSubsystem.h"
AddReplicatedSubObject(MySubObject, COND_NetGroup); // on the owning actor/component
UNetworkSubsystem* NetSubsystem = GetWorld()->GetSubsystem<UNetworkSubsystem>();
NetSubsystem->GetNetConditionGroupManager().RegisterSubObjectInGroup(MySubObject, FName("RedTeam"));
MyPlayerController->IncludeInNetConditionGroup(FName("RedTeam"));
UE::Net::NetGroupOwner と UE::Net::NetGroupReplay はエンジンが管理するグループです。プレイヤーコントローラーを追加しないでください。APlayerController は RemoveFromNetConditionGroup、IsMemberOfNetConditionGroup、GetNetConditionGroups も公開しています。
Push Model
Push model では、複製されるプロパティのフレームごとの memcmp がなくなります。プロパティは、ダーティとしてマークしたときにのみ比較されます。クラシックなネットドライバーと Iris の両方で動作します。Iris の機能ではありません。
// MyPushActor.cpp
#include "MyPushActor.h"
#include "Net/UnrealNetwork.h"
#include "Net/Core/PushModel/PushModel.h"
void AMyPushActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
FDoRepLifetimeParams Params;
Params.bIsPushBased = true;
Params.Condition = COND_OwnerOnly;
DOREPLIFETIME_WITH_PARAMS_FAST(AMyPushActor, Ammo, Params);
}
void AMyPushActor::ConsumeAmmo(int32 Count)
{
if (!HasAuthority())
{
return;
}
Ammo -= Count;
MARK_PROPERTY_DIRTY_FROM_NAME(AMyPushActor, Ammo, this);
}
MARK_PROPERTY_DIRTY_FROM_NAME(ClassName, PropertyName, Object)が推奨されるマーカーです。静的配列には、MARK_PROPERTY_DIRTY_FROM_NAME_STATIC_ARRAY_INDEX(ClassName, PropertyName, ArrayIndex, Object)またはMARK_PROPERTY_DIRTY_FROM_NAME_STATIC_ARRAY(ClassName, PropertyName, Object)を使用します。- 2 か所で有効にします。ゲーム/サーバーの
*.Target.csでbWithPushModel = true;(デフォルトで true になるのは Editor ターゲットのみです。TargetRules.cs:1524)と、Net.IsPushModelEnabled=1(デフォルトは false です。PushModel.cpp:434)を設定します。両方を有効にするまでは、通常どおりプロパティが比較されます。 WITH_PUSH_MODELがオフの場合、マクロは何も出力しないため、このコードは常に安全にリリースできます(例外:Push Model 無効時のMARK_PROPERTY_DIRTY_FROM_NAME_STATIC_ARRAYのスタブは 4 つの引数を取るため(PushModel.h:489)、3 引数の形式はそこでコンパイルに失敗します)。- 参照を介して変更される構造体プロパティには、参照を渡す前にダーティとしてマークするアクセサーが必要です。
- Push Model を有効にすると、マーカーを 1 つでも付け忘れた場合、そのプロパティは何も通知されずに複製されなくなります。これが有効化する際の主なコストです。
Fast Array Serialization
FFastArraySerializer は、配列全体ではなく変更されたアイテムだけを送信します。
#include "Net/Serialization/FastArraySerializer.h" // module NetCore
アイテム構造体は FFastArraySerializerItem を継承し、次のいずれかを実装できます。
void PreReplicatedRemove(const struct FMyItemArray& InArraySerializer);
void PostReplicatedAdd(const struct FMyItemArray& InArraySerializer);
void PostReplicatedChange(const struct FMyItemArray& InArraySerializer);
配列構造体は FFastArraySerializer を継承し、FastArrayDeltaSerialize<ItemType, ArrayType>(Items, DeltaParms, *this) を介して NetDeltaSerialize を実装する必要があります。また、TStructOpsTypeTraits<...> { WithNetDeltaSerializer = true } も必要です。さらに、配列レベルの受信フックを実装できます。
void PostReplicatedReceive(const FFastArraySerializer::FPostReplicatedReceiveParameters& Parameters);
FPostReplicatedReceiveParameters::OldArraySize は更新前のサイズです。そのため、「リスト全体が変更されたので UI を再構築する」といった処理に適しています。
ダーティのルール — 以下の 2 つはどちらも必須で、「配列が複製されない」という問題のよくある原因でもあります。
- アイテムの追加後または変更後に
MarkItemDirty(Item)を呼び出します。 - アイテムの削除後に
MarkArrayDirty()を呼び出します(ID マップも無効化されます)。
インベントリ全体の実装:複製パターン、パターン 3。
リモートプロシージャコール
UFUNCTION のネットワーク指定子(UObject/ObjectMacros.h):Server、Client、NetMulticast、Reliable、Unreliable、WithValidation、BlueprintAuthorityOnly、BlueprintCosmetic。Reliable/Unreliable は、Server、Client、NetMulticast のいずれかと併用する場合のみ有効です。
// Client calls, server executes. WithValidation generates the _Validate pair.
UFUNCTION(Server, Reliable, WithValidation)
void ServerFireWeapon(FVector_NetQuantize Origin, FVector_NetQuantizeNormal Direction);
// Server calls, the owning client executes.
UFUNCTION(Client, Reliable)
void ClientShowKillConfirm(int32 VictimId);
// Server calls, server and every client with this actor relevant execute.
UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayHitEffect(FVector_NetQuantize ImpactPoint);
_Implementation の本体を記述します。WithValidation を指定した場合は _Validate も記述し、false を返すと呼び出し元の接続が切断されます。
| ルール | 詳細 |
|---|---|
| 所有権 | Server RPC がルーティングされるのは、呼び出し元のクライアントが SetOwner のチェーンを通じて APlayerController までアクターを所有している場合のみです。所有者のいないアクターへの呼び出しは破棄されます。確認できるのは LogNet の警告「No owning connection for actor…」のみです(NetDriver.cpp:8274)。 |
| クライアント RPC の送信先 | 所有する接続が存在するアクターが必要です。APlayerController を使うのが確実です。 |
| 信頼性 | 状態変更には Reliable、高頻度の演出には Unreliable を使用します。毎ティック Reliable RPC を送信しないでください。未確認の信頼性付きバンチがチャネル上で RELIABLE_BUFFER(512、NetConnection.h:82)を超えると、接続は ReliableBufferOverflow で閉じられます(DataChannel.cpp:1445)。 |
| 途中参加者 | マルチキャストは再生されません。永続的な状態はレプリケーションされたプロパティに保持してください。 |
| パラメーター | ネットワークアドレス指定可能な型のみ使用できます。レプリケーションされておらず、安定した名前も持たない UObject*(アセット、クラス、マップに配置されたアクター)は nullptr として届きます。ID を渡して、リモート側で解決してください。 |
| 方向 | クライアントで呼び出された Client/NetMulticast は送信されず、そのクライアント上でローカル実行されるだけです(Actor.cpp:5569-5573、5587-5592)。呼び出し箇所を HasAuthority() でガードしてください。 |
判定表、信頼性マトリクス、PlayerController.h の宣言の原文については、RPC 判定ガイドを参照してください。
所有権、関連性、休止状態
Weapon->SetOwner(OwningPlayerController); // server only; drives RPC routing and COND_OwnerOnly
AActor の関連性フィールドとフック:
bAlwaysRelevant = true; // ignore distance culling
bOnlyRelevantToOwner = true; // owner connection only
virtual bool IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const override;
virtual float GetNetPriority(const FVector& ViewPos, const FVector& ViewDir, AActor* Viewer, AActor* ViewTarget, UActorChannel* InChannel, float Time, bool bLowBandwidth) override;
SetNetCullDistanceSquared() は半径の二乗を設定します。NetPriority は帯域幅が飽和した際の優先順位を決め、GetReplayPriority() はリプレイの記録で同様に機能します。
休止状態(EngineTypes.h の ENetDormancy:DORM_Never、DORM_Awake、DORM_DormantAll、DORM_DormantPartial、DORM_Initial):
NetDormancy = DORM_Initial; // constructor: map-placed actors start dormant
SetNetDormancy(DORM_DormantAll); // runtime
FlushNetDormancy(); // push one update, then return to dormant
休止状態から復帰したアクターは、接続が休止状態に入ったときに保持していたレプリケーターとの差分が取られるため(DataChannel.cpp:2510-2519)、通常は変更箇所のみが送信されます。関連性がなくなってチャネルが閉じたアクターが範囲内に再び入ると、完全な初期バンチが送信され、そのアクターの OnRep_ が再度実行されます。繰り返しの呼び出しに対応できる OnRep_ ハンドラーを記述してください。
サブオブジェクトのレプリケーション
5.8 では、bReplicateUsingRegisteredSubObjectList のデフォルト値は false です(Engine/Private/Components/ActorComponent.cpp の GDefaultUseSubObjectReplicationList = false、プロジェクト全体の CVar は net.SubObjects.DefaultUseSubObjectReplicationList)。クラスごとに有効にしてください。有効にしないと、登録したものは何もレプリケートされません。
AMyQuestActor::AMyQuestActor()
{
bReplicates = true;
bReplicateUsingRegisteredSubObjectList = true; // protected field; set in the constructor
}
AActor の登録 API(GameFramework/Actor.h)。UActorComponent(Components/ActorComponent.h)にも ActorComponent の各バリアント以外は同じ API があります。
void AddReplicatedSubObject(UObject* SubObject, ELifetimeCondition NetCondition = COND_None);
void RemoveReplicatedSubObject(UObject* SubObject);
void AddActorComponentReplicatedSubObject(UActorComponent* OwnerComponent, UObject* SubObject, ELifetimeCondition NetCondition = COND_None);
void RemoveActorComponentReplicatedSubObject(UActorComponent* OwnerComponent, UObject* SubObject);
void DestroyReplicatedSubObjectOnRemotePeers(UObject* SubObject);
void TearOffReplicatedSubObjectOnRemotePeers(UObject* SubObject);
bool IsUsingRegisteredSubObjectList() const;
RemoveReplicatedSubObject は、以降の更新を停止するだけで、クライアント側にはコピーが残ります。リモート側で削除するには DestroyReplicatedSubObjectOnRemotePeers を使用し、ローカルに孤立したコピーを残すには TearOffReplicatedSubObjectOnRemotePeers を使用してください。サブオブジェクトは virtual bool IsSupportedForNetworking() const をオーバーライドして true を返し、独自の GetLifetimeReplicatedProps を宣言する必要があります。
このフラグが false の場合、エンジンは代わりに、引き続き有効な次の仮想関数を呼び出します。
virtual bool ReplicateSubobjects(class UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags) override;
この関数内で Super:: に転送し、Channel->ReplicateSubobject(SubObject, *Bunch, *RepFlags) を呼び出します。登録済みサブオブジェクトについては、レプリケーションパターン、パターン 5を参照してください。
物理レプリケーション
EPhysicsReplicationMode(EngineTypes.h)では、シミュレーション中のボディを補正する方法として、Default、PredictiveInterpolation、Resimulation、Noneを選択します。
SetPhysicsReplicationMode(EPhysicsReplicationMode::PredictiveInterpolation);
EPhysicsReplicationMode Mode = GetPhysicsReplicationMode();
PredictiveInterpolationとResimulationを使用するには、Project Settings → Physics → Physics Predictionが必要です。相互作用するすべてのボディで、同じモードを使用してください。ロールバック方式のネットワーク物理には、UNetworkPhysicsComponent(Engine/Public/Physics/NetworkPhysicsComponent.h)と、APlayerControllerのFAsyncPhysicsTimestampハンドシェイク(ClientSetupNetworkPhysicsTimestamp、ServerSendLatestAsyncPhysicsTimestamp)を使用してください。コリジョンとボディの設定については、ue-physics-collisionを参照してください。
Iris レプリケーションシステム
Irisは代替のレプリケーションバックエンドです(プラグインIris。5.8ではベータフラグ付き。Epicの5.8リリースノートでは、ライセンシー向けに本番環境で使用可能とされています)。ランタイムモジュールはSource/Runtime/Net/IrisのIrisCore、エンジンとの連携部分はEngine/Public/Net/Irisにあります。
- モジュールのBuild.csで有効にします:
SetupIrisSupport(Target); Irisプラグイン(EnabledByDefault: false)を有効にし、ランタイムスイッチnet.Iris.UseIrisReplication=1を設定します。デフォルトは0で、従来のレプリケーションシステムが使用されます(IrisConfig.cpp:14)。- プロパティの宣言、RPC、条件、プッシュモデルに変更はありません。Irisが変更するのはバックエンドであり、ゲームプレイ向けのAPIではありません。
Irisが有効な場合のアクターフック(GameFramework/Actor.h):
virtual void FillReplicationParams(const FFillReplicationParamsContext& Context, FActorReplicationParams& OutParams) override; // public
virtual void OnReplicationStartedForIris(const FOnReplicationStartedParams&) override; // protected
virtual void OnStopReplicationForIris(const FOnStopReplicationParams&) override; // protected
UReplicationBridgeとUObjectReplicationBridge(Iris/ReplicationSystem/)は内部実装です。ゲームプレイコードでこれらを派生元にしないでください。UReplicationBridgeには、以前あった独立した基底クラスがなくなっています。内部実装として扱ってください。
レプリケーショングラフ
接続数が多い場合は、接続ごとの関連性スキャンをReplicationGraphプラグインに置き換えます(5.8ではベータ)。Build.csのモジュール:ReplicationGraph。
; DefaultEngine.ini
[/Script/OnlineSubsystemUtils.IpNetDriver]
ReplicationDriverClassName="/Script/MyGame.MyReplicationGraph"
// MyReplicationGraph.h
#pragma once
#include "CoreMinimal.h"
#include "ReplicationGraph.h"
#include "MyReplicationGraph.generated.h"
UCLASS()
class MYGAME_API UMyReplicationGraph : public UReplicationGraph
{
GENERATED_BODY()
public:
virtual void InitGlobalActorClassSettings() override;
virtual void InitGlobalGraphNodes() override;
virtual void InitConnectionGraphNodes(UNetReplicationGraphConnection* ConnectionManager) override;
};
ノードクラス(ReplicationGraph.h):UReplicationGraphNode_GridSpatialization2D(ワールドグリッド)、UReplicationGraphNode_AlwaysRelevant(ゲームステート、マネージャー)、UReplicationGraphNode_AlwaysRelevant_ForConnection(コントローラー、プレイヤーステート)、UReplicationGraphNode_ActorList(手動で構築するリスト)、UReplicationGraphNode_DormancyNode、UReplicationGraphNode_DynamicSpatialFrequency。
ネットドライバーと接続
UNetDriver(Engine/Classes/Engine/NetDriver.h)は接続を管理し、ワールドのレプリケーションを駆動します。
if (UNetDriver* Driver = GetWorld()->GetNetDriver())
{
// Driver->ClientConnections — server side, one per client
// Driver->ServerConnection — client side, the single upstream connection
}
UNetConnection(Engine/Classes/Engine/NetConnection.h)は、1つのクライアントの接続を表します。AActor::GetNetConnection()(APlayerControllerでオーバーライドされています)を使って取得します。画面分割プレイヤーには、親接続に接続されたUChildConnection(Engine/ChildConnection.h)が割り当てられます。
UE::Net::FConnectionHandle Handle = Connection->GetConnectionHandle();
UNetConnection* Found = Driver->GetConnectionByHandle(Handle);
const bool bGone = Connection->IsClosingOrClosed(); // USOCK_Closing or USOCK_Closed
EConnectionState State = Connection->GetConnectionState();
接続状態をポーリングするよりも、切断処理にはAGameModeBase::Logoutを使用してください。
APlayerControllerはサーバーと、それを所有するクライアントにのみ存在します。すべてのクライアントが必要とするデータは、APawn、APlayerState、またはAGameStateBaseに配置してください。詳しくはue-gameplay-frameworkを参照してください。
非推奨 — 使用しないでください
| 出力しない | 5.8 で使用 | ソース |
|---|---|---|
NetUpdateFrequency = X; | SetNetUpdateFrequency(X) / GetNetUpdateFrequency() | GameFramework/Actor.h の UE_DEPRECATED(5.5) |
MinNetUpdateFrequency = X; | SetMinNetUpdateFrequency(X) / GetMinNetUpdateFrequency() | GameFramework/Actor.h の UE_DEPRECATED(5.5) |
NetCullDistanceSquared = X; | SetNetCullDistanceSquared(X) / GetNetCullDistanceSquared() | GameFramework/Actor.h の UE_DEPRECATED(5.5) |
virtual void BeginReplication() | OnReplicationStartedForIris または FillReplicationParams | GameFramework/Actor.h の UE_DEPRECATED(5.7) |
virtual void EndReplication(EEndPlayReason::Type) | OnStopReplicationForIris | GameFramework/Actor.h の UE_DEPRECATED(5.7) |
BeginReplication(const FActorReplicationParams&) | FillReplicationParams をオーバーライド | GameFramework/Actor.h の UE_DEPRECATED(5.7) |
UNetConnection::GetConnectionId() | GetConnectionHandle() | Engine/NetConnection.h の UE_DEPRECATED(5.6) |
UNetConnection::SetConnectionId() | なし — 外部コードから設定してはいけません(SetConnectionHandle() は保護されています。NetConnection.h:2006) | Engine/NetConnection.h の UE_DEPRECATED(5.6) |
UNetConnection::GetParentConnectionId() | GetConnectionHandle() | Engine/NetConnection.h の UE_DEPRECATED(5.6) |
UNetDriver::GetConnectionById(uint32) | GetConnectionByHandle(FConnectionHandle) | Engine/NetDriver.h の UE_DEPRECATED(5.6) |
UNetDriver::SetPendingDestruction() | RequestNetDriverDestruction() | Engine/NetDriver.h の UE_DEPRECATED(5.6) |
FPostReplicatedReceiveParameters::bHasMoreUnmappedReferences | OldArraySize のみを読み取る | Net/Serialization/FastArraySerializer.h の UE_DEPRECATED(5.4) |
UObjectReplicationBridge::DetachInstanceFromRemote | DetachRootObjectFromRemote / DetachSubObjectFromRemote | Iris/ReplicationSystem/ObjectReplicationBridge.h の UE_DEPRECATED(5.8) |
UNetObjectFactory::FDestroyedContext | FDetachContext | Iris/ReplicationSystem/NetObjectFactory.h の UE_DEPRECATED(5.8) |
よくある間違い
登録済みサブオブジェクトリストが有効だと思い込む: デフォルトでは false なので、AddReplicatedSubObject だけでは何もレプリケートされません。コンストラクターで bReplicateUsingRegisteredSubObjectList = true を設定する(または net.SubObjects.DefaultUseSubObjectReplicationList を切り替える)とともに、IsUsingRegisteredSubObjectList() で確認してください。
Super::GetLifetimeReplicatedProps を呼び出さない: AActor や APawn のエンジン状態を含む、継承されたレプリケート対象プロパティがすべて失われます。必ず最初に Super を呼び出してください。
クライアントでレプリケート対象の状態を変更する: 次のサーバー更新で上書きされ、ロールバックも行われません。if (!HasAuthority()) return; でガードし、OnRep_ で権威ある値を適用してください。
マーカーなしでプッシュモデルを使用する: Params.bIsPushBased = true として宣言されたプロパティにダーティマークを付けないと、レプリケーションが停止します。すべての書き込み経路で MARK_PROPERTY_DIRTY_FROM_NAME が必要です。
MarkArrayDirty() を呼び出さずに高速配列から削除する: 削除がクライアントに届きません。MarkItemDirty が対象とするのは変更のみです。
永続状態に NetMulticast を使用する: 後から参加したクライアントには届きません。マルチキャストは一度限りの演出に使用し、状態はレプリケート対象プロパティに保持してください。
所有者のいないアクターでサーバー RPC を呼び出す: LogNet の警告だけが出て、呼び出しは破棄されます。スポーン後にサーバーで SetOwner() を呼び出し、APlayerController まで所有関係の連鎖を維持してください。
UFUNCTION ではない OnRep_: 通常のメンバー関数を参照する ReplicatedUsing は UHT に拒否されます。その上に UFUNCTION() を宣言してください。
状態を変更する WithValidation のないサーバー RPC: クライアントは任意のパラメーター値を送信できます。_Validate で検証するか、さらに望ましい方法として ID を送信し、サーバー側で権威あるデータを検索してください。
冪等でない OnRep_: 関連性が変わると状態全体が再送され、コールバックも再度実行されます。OnRep_ を「厳密に一度だけ」実行されるイベントとして扱わないでください。
関連スキル
ue-cpp-foundations—UPROPERTY/UFUNCTION指定子のリファレンス、モジュールのインクルード、リフレクションの基本ue-gameplay-framework—AGameModeBase(サーバーのみ)、AGameStateBase/APlayerStateのレプリケーション範囲、APawnのポゼッションue-gameplay-abilities— GAS の予測キー、属性セットのレプリケーション、ゲームプレイエフェクトのレプリケーションモードue-character-movement— CMC の移動レプリケーション、保存された移動、サーバーによる補正とネットワークスムージングue-actor-component-architecture— コンポーネントのライフサイクル、SetIsReplicated、サブオブジェクトの所有権ue-async-threading— レプリケートされる状態に反映するオフスレッド処理、タスクグラフと非同期パターンue-serialization-savegames— セッションをまたぐ状態の永続化、NetSerializeとSerializeの違いue-gameplay-tags-messaging— ネイティブおよび ini のゲームプレイタグ、コンテナ、クエリ、非同期メッセージシステムue-mover— Mover プラグイン:移動モード、レイヤー化された移動、ロールバックネットワークue-physics-collision— コリジョンチャンネル、トレース、オーバーラップ、Chaos 物理ue-world-level-streaming— World Partition、レベルストリーミング、データレイヤー、トラベル