mcpField
U
ue-networking-replication

ue-networking-replication

github.com/quodsoler開発4191.2k 回インストール4 週間前に更新
リポジトリ

ue-networking-replication について

Unreal Engine 5.8 開発者向けのネットワーク・レプリケーションスキルです。サーバー権限、プロパティや RPC、Fast Array、Push Model、追加のレプリケーションシステムを解説します。

主な機能

  1. 01ネットワークロールと権限判定
  2. 02プロパティ複製とライフタイム条件
  3. 03Push Model のダーティーマーク
  4. 04Fast Array の差分シリアライズ
  5. 05Server、Client、Multicast RPC
  6. 06Iris と Replication Graph

活用シーン

  1. 01Actor のプロパティと移動状態の複製
  2. 02接続ごとのプロパティ配信制御
  3. 03更新されるインベントリ配列の複製
  4. 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.UseIrisReplicationIris レプリケーションシステム
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_AuthorityROLE_AutonomousProxy または ROLE_SimulatedProxy
所有クライアントROLE_AutonomousProxyROLE_Authority
その他のクライアントROLE_SimulatedProxyROLE_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 または FillReplicationParamsGameFramework/Actor.h の UE_DEPRECATED(5.7)
virtual void EndReplication(EEndPlayReason::Type)OnStopReplicationForIrisGameFramework/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::bHasMoreUnmappedReferencesOldArraySize のみを読み取るNet/Serialization/FastArraySerializer.h の UE_DEPRECATED(5.4)
UObjectReplicationBridge::DetachInstanceFromRemoteDetachRootObjectFromRemote / DetachSubObjectFromRemoteIris/ReplicationSystem/ObjectReplicationBridge.h の UE_DEPRECATED(5.8)
UNetObjectFactory::FDestroyedContextFDetachContextIris/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、レベルストリーミング、データレイヤー、トラベル

コメント