К основному содержанию
скилл CX Codex

ue-networking-replication — скилл для Claude Code: репликация в Unreal

Скилл для написания сетевого C++ в Unreal Engine: репликация свойств, RPC, dormancy, сабобъекты. Пригодится, когда нужно разобраться с авторитетом сервера.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add quodsoler/unreal-engine-skills --skill ue-networking-replication -a claude-code
Открыть на GitHub

Что делает ue-networking-replication

Скилл закрывает серверную репликацию акторов, компонентов и сабобъектов в Unreal Engine 5.8. Внутри — таблицы ролей ENetRole и режимов ENetMode, правила GetLifetimeReplicatedProps, условия COND_*, push model, FFastArraySerializer, RPC с валидацией, владение и dormancy, физическая репликация, Iris и Replication Graph. Отдельные справочники: готовые примеры паттернов и таблицы выбора RPC.

Скилл сам читает .agents/ue-project-context.md, если файл есть в проекте, и по нему определяет имена модулей и включённые плагины. Если файла нет — работает дальше, но контекст придётся описывать в запросе. Это повод завести такой файл заранее: без него агент чаще переспрашивает.

Целевая версия — UE 5.8, API сверены с её заголовками, устаревшие формы вынесены в отдельный раздел. Replication Graph в 5.8 помечен как Beta, а Iris включается через SetupIrisSupport(Target) в Build.cs. Для GAS-предсказания и репликации атрибутов скилл отправляет к ue-gameplay-abilities, для движения и CMC — к ue-character-movement.

Какие задачи решает

  • включить репликацию свойства и повесить на него OnRep_
  • выбрать между Server RPC, Client RPC и NetMulticast
  • ограничить свойство условием COND_OwnerOnly или COND_InitialOnly
  • зарегистрировать реплицируемый сабобъект у актора
  • перевести проект на push model или Iris

Примеры запросов агенту

  • Сделай так, чтобы Health реплицировался и вызывал OnRep_Health на клиентах
  • Какой RPC выбрать для урона: Server, Client или NetMulticast?
  • Настрой dormancy для этого актора и объясни, когда он перестанет обновляться

Как установить ue-networking-replication

1Через Skills CLI (Vercel)

npx skills add quodsoler/unreal-engine-skills --skill ue-networking-replication -a claude-code

2Вручную: положить файлы

~/.claude/skills/ue-networking-replication/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/ue-networking-replication/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о ue-networking-replication

Как установить ue-networking-replication в Claude?

Выполните npx skills add quodsoler/unreal-engine-skills --skill ue-networking-replication -a claude-code. Скилл окажется в ~/.claude/skills/ue-networking-replication/SKILL.md.

Что делает ue-networking-replication?

Помогает писать сетевой C++ в Unreal: репликация свойств, RPC, условия COND_*, dormancy, сабобъекты, push model, Iris и Replication Graph.

Чем этот скилл отличается от ue-gameplay-abilities и ue-character-movement?

Он про общую репликацию акторов и компонентов. Предсказание GAS и репликацию атрибутов отдаёт скиллу ue-gameplay-abilities, а репликацию движения и предсказание CMC — ue-character-movement.

Исходный текст

SKILL.md · MIT
---
name: ue-networking-replication
description: "Use when writing multiplayer C++: replicating a property, choosing an RPC type, tuning relevancy or dormancy, registering replicated subobjects, or turning on push model or Iris. Also use when the user mentions 'replicate a variable', 'OnRep', 'DOREPLIFETIME', 'GetLifetimeReplicatedProps', 'Server RPC', 'NetMulticast', 'WithValidation', 'COND_OwnerOnly', 'HasAuthority', 'ENetRole', 'FFastArraySerializer', 'MARK_PROPERTY_DIRTY_FROM_NAME', 'net dormancy', 'replication graph', 'dedicated server' or 'listen server'. For GAS prediction and attribute replication, see ue-gameplay-abilities; for movement replication and CMC prediction, see ue-character-movement."
metadata:
  version: "2.0.0"
  engine: "5.8"
---

# UE Networking & Replication

Target engine: **UE 5.8**. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".

Server-authoritative replication for actors, components and subobjects. Core APIs live in the `Engine` module (`GameFramework/Actor.h`, `Engine/NetDriver.h`, `Net/UnrealNetwork.h`) and the `NetCore` module (`Net/Core/PushModel/PushModel.h`, `Net/Serialization/FastArraySerializer.h`). `ELifetimeCondition` and `REPNOTIFY_*` come from `CoreUObject` (`UObject/CoreNetTypes.h`). Optional systems: the Iris replication system (`IrisCore` module, `SetupIrisSupport(Target)` in Build.cs) and the ReplicationGraph plugin (Beta in 5.8, Build.cs module `ReplicationGraph`).

## Context

Read `.agents/ue-project-context.md` if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.

Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.

| Request is about… | Go to |
|---|---|
| Authority checks, roles, dedicated vs listen server | [Net Roles, Net Modes and Authority](#net-roles-net-modes-and-authority) |
| Replicating a variable, `OnRep_`, `GetLifetimeReplicatedProps` | [Property Replication](#property-replication) |
| Who receives a property (`COND_*`) | [Lifetime Conditions](#lifetime-conditions) |
| Cutting per-frame comparison cost | [Push Model](#push-model) |
| Replicated arrays / inventories | [Fast Array Serialization](#fast-array-serialization) |
| Server/Client/Multicast calls, validation | [Remote Procedure Calls](#remote-procedure-calls) |
| `SetOwner`, relevancy, culling, dormancy | [Ownership, Relevancy and Dormancy](#ownership-relevancy-and-dormancy) |
| Replicating `UObject`s owned by an actor or component | [Subobject Replication](#subobject-replication) |
| Simulated bodies, physics prediction | [Physics Replication](#physics-replication) |
| Iris, `net.Iris.UseIrisReplication` | [Iris Replication System](#iris-replication-system) |
| 50+ connections, spatial relevancy | [Replication Graph](#replication-graph) |
| `UNetDriver`, `UNetConnection`, disconnect detection | [Net Driver and Connections](#net-driver-and-connections) |

Worked end-to-end examples: [replication patterns](references/replication-patterns.md). RPC selection tables and verbatim engine RPC declarations: [RPC decision guide](references/rpc-decision-guide.md).

## Net Roles, Net Modes and Authority

`ENetRole` is declared in `Engine/Classes/Engine/EngineTypes.h`; the accessors are on `AActor`.

```cpp
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
```

From `GameFramework/Actor.h`:

```cpp
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`. Every mode below `NM_Client` is a server.

| Machine | `GetLocalRole()` | `GetRemoteRole()` |
|---|---|---|
| Server | `ROLE_Authority` | `ROLE_AutonomousProxy` or `ROLE_SimulatedProxy` |
| Owning client | `ROLE_AutonomousProxy` | `ROLE_Authority` |
| Other clients | `ROLE_SimulatedProxy` | `ROLE_Authority` |

On a listen server the host is `ROLE_Authority` *and* locally controlled: use `APawn::IsLocallyControlled()` to skip host-only or client-only paths.

## Property Replication

```cpp
// 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);
};
```

```cpp
// 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.
}
```

Rules:

- `OnRep_` must be a `UFUNCTION()`. Its optional single parameter is the **previous** value and must match the property type.
- Only the authority may write a replicated property. `OnRep_` does not fire on the machine that made the change.
- `UPROPERTY(NotReplicated)` inside a replicated struct excludes a member.
- `FVector_NetQuantize` / `_NetQuantize10` / `_NetQuantize100` / `_NetQuantizeNormal` (`Engine/NetSerialization.h`) cut world-position bandwidth: 0, 1 and 2 decimal places, and 16 bits per component for normals.
- `FRepMovement` (`Engine/Classes/Engine/ReplicatedState.h`) carries location/rotation/velocity when `SetReplicateMovement(true)`; override `virtual void OnRep_ReplicatedMovement()` to post-process it. `UCharacterMovementComponent` replicates moves itself — see `ue-character-movement`.
- On the first bunch for a connection, every eligible property is sent at once. Keep initial state small and push spawn-only data behind `COND_InitialOnly`.

Macros (`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`) is the struct behind the `_WITH_PARAMS` forms:

```cpp
ELifetimeCondition Condition = COND_None;
ELifetimeRepNotifyCondition RepNotifyCondition = REPNOTIFY_OnChanged; // or REPNOTIFY_Always
bool bIsPushBased = false;
```

## Lifetime Conditions

Full `ELifetimeCondition` enum, `CoreUObject/Public/UObject/CoreNetTypes.h`:

| Value | Sends to |
|---|---|
| `COND_None` | every connection |
| `COND_InitialOnly` | initial bunch only |
| `COND_OwnerOnly` | the actor's owning connection |
| `COND_SkipOwner` | everyone except the owner |
| `COND_SimulatedOnly` | connections where the actor is a simulated proxy |
| `COND_AutonomousOnly` | connections where the actor is an autonomous proxy |
| `COND_SimulatedOrPhysics` | simulated proxies or `bRepPhysics` actors |
| `COND_InitialOrOwner` | initial bunch, or the owner |
| `COND_Custom` | always eligible; toggled at runtime via the active-override macros |
| `COND_ReplayOrOwner` | replay connection or the owner |
| `COND_ReplayOnly` | replay connection only |
| `COND_SimulatedOnlyNoReplay` | simulated proxies, never replay |
| `COND_SimulatedOrPhysicsNoReplay` | simulated or `bRepPhysics`, never replay |
| `COND_SkipReplay` | everything except the replay connection |
| `COND_Dynamic` | condition is overridden at runtime; replicates until you set one |
| `COND_Never` | never replicated |
| `COND_NetGroup` | **subobjects only** — connections in the same net condition group |

`COND_NetGroup` pairs with `UE::Net::FNetConditionGroupManager` (`Net/Core/Misc/NetConditionGroupManager.h`, module `NetCore`), reached through `UNetworkSubsystem::GetNetConditionGroupManager()` (`Net/Subsystems/NetworkSubsystem.h`):

```cpp
#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` and `UE::Net::NetGroupReplay` are engine-managed groups; do not add a player controller to them. `APlayerController` also exposes `RemoveFromNetConditionGroup`, `IsMemberOfNetConditionGroup` and `GetNetConditionGroups`.

## Push Model

Push model removes the per-frame memcmp of replicated properties: the property is only compared when you mark it dirty. It works with the **classic** net driver and with Iris — it is not an Iris feature.

```cpp
// 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)` is the preferred marker. Static arrays use `MARK_PROPERTY_DIRTY_FROM_NAME_STATIC_ARRAY_INDEX(ClassName, PropertyName, ArrayIndex, Object)` or `MARK_PROPERTY_DIRTY_FROM_NAME_STATIC_ARRAY(ClassName, PropertyName, Object)`.
- Opt in twice: `bWithPushModel = true;` in the game/server `*.Target.cs` (defaults to true only for Editor targets, `TargetRules.cs:1524`) and `Net.IsPushModelEnabled=1` (defaults to false, `PushModel.cpp:434`). Until both are on, properties are compared as usual.
- The macros compile to nothing when `WITH_PUSH_MODEL` is off, so the code is always safe to ship (exception: the no-push `MARK_PROPERTY_DIRTY_FROM_NAME_STATIC_ARRAY` stub takes 4 arguments, `PushModel.h:489`, so the 3-argument form fails to compile there).
- A struct property mutated by reference needs an accessor that marks it dirty before handing out the reference.
- With push model enabled, forgetting one marker means the property silently stops replicating — this is the main cost of opting in.

## Fast Array Serialization

`FFastArraySerializer` sends only changed items instead of the whole array.

```cpp
#include "Net/Serialization/FastArraySerializer.h"   // module NetCore
```

Item struct derives from `FFastArraySerializerItem` and may implement any of:

```cpp
void PreReplicatedRemove(const struct FMyItemArray& InArraySerializer);
void PostReplicatedAdd(const struct FMyItemArray& InArraySerializer);
void PostReplicatedChange(const struct FMyItemArray& InArraySerializer);
```

The array struct derives from `FFastArraySerializer`, implements `NetDeltaSerialize` via `FastArrayDeltaSerialize<ItemType, ArrayType>(Items, DeltaParms, *this)`, and needs `TStructOpsTypeTraits<...> { WithNetDeltaSerializer = true }`. It may also implement the array-level receive hook:

```cpp
void PostReplicatedReceive(const FFastArraySerializer::FPostReplicatedReceiveParameters& Parameters);
```

`FPostReplicatedReceiveParameters::OldArraySize` is the size before the update, which makes this the right place for "the whole list changed, rebuild the UI" work.

Dirty rules — both are mandatory, and both are common sources of "my array does not replicate":

- `MarkItemDirty(Item)` after adding or mutating an item.
- `MarkArrayDirty()` after **removing** an item (it also invalidates the ID map).

Full inventory implementation: [replication patterns, Pattern 3](references/replication-patterns.md).

## Remote Procedure Calls

`UFUNCTION` network specifiers (`UObject/ObjectMacros.h`): `Server`, `Client`, `NetMulticast`, `Reliable`, `Unreliable`, `WithValidation`, `BlueprintAuthorityOnly`, `BlueprintCosmetic`. `Reliable`/`Unreliable` are only valid together with `Server`, `Client` or `NetMulticast`.

```cpp
// 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);
```

You write `_Implementation` bodies; with `WithValidation` you also write `_Validate`, and returning `false` disconnects the caller.

| Rule | Detail |
|---|---|
| Ownership | A `Server` RPC only routes if the calling client owns the actor through its `SetOwner` chain up to its `APlayerController`. Unowned actors drop the call; the only trace is a `LogNet` Warning "No owning connection for actor…" (`NetDriver.cpp:8274`). |
| Client RPC target | Needs an actor whose owning connection exists; `APlayerController` is the reliable choice. |
| Reliability | `Reliable` for state changes, `Unreliable` for high-frequency cosmetics. Do not send `Reliable` RPCs every tick: once a channel has more than `RELIABLE_BUFFER` (512, `NetConnection.h:82`) unacked reliable bunches the connection is closed with `ReliableBufferOverflow` (`DataChannel.cpp:1445`). |
| Late joiners | Multicasts are not replayed. Persistent state belongs in a replicated property. |
| Parameters | Net-addressable types only. A `UObject*` that is neither replicated nor stably named (asset, class, map-placed actor) arrives as `nullptr`; pass an id and resolve remotely. |
| Direction | `Client`/`NetMulticast` called on a client are never sent; they just run locally on that client (`Actor.cpp:5569-5573`, `5587-5592`). Guard call sites with `HasAuthority()`. |

Decision tables, reliability matrices and verbatim `PlayerController.h` declarations: [RPC decision guide](references/rpc-decision-guide.md).

## Ownership, Relevancy and Dormancy

```cpp
Weapon->SetOwner(OwningPlayerController);   // server only; drives RPC routing and COND_OwnerOnly
```

Relevancy fields and hooks on `AActor`:

```cpp
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()` sets the squared radius; `NetPriority` breaks ties when bandwidth saturates; `GetReplayPriority()` does the same for replay recording.

Dormancy (`ENetDormancy` in `EngineTypes.h`: `DORM_Never`, `DORM_Awake`, `DORM_DormantAll`, `DORM_DormantPartial`, `DORM_Initial`):

```cpp
NetDormancy = DORM_Initial;        // constructor: map-placed actors start dormant
SetNetDormancy(DORM_DormantAll);   // runtime
FlushNetDormancy();                // push one update, then return to dormant
```

A waking dormant actor is diffed against the replicator the connection kept when it went dormant (`DataChannel.cpp:2510-2519`), so normally only changes are sent; an actor whose channel closed on relevancy gets a full initial bunch when it re-enters range, which fires its `OnRep_`s again. Write `OnRep_` handlers that tolerate repeats.

## Subobject Replication

`bReplicateUsingRegisteredSubObjectList` defaults to **false** in 5.8 (`GDefaultUseSubObjectReplicationList = false` in `Engine/Private/Components/ActorComponent.cpp`, project-wide CVar `net.SubObjects.DefaultUseSubObjectReplicationList`). Opt in per class, or nothing you register replicates:

```cpp
AMyQuestActor::AMyQuestActor()
{
    bReplicates = true;
    bReplicateUsingRegisteredSubObjectList = true;  // protected field; set in the constructor
}
```

`AActor` registration API (`GameFramework/Actor.h`); `UActorComponent` (`Components/ActorComponent.h`) mirrors all but the `ActorComponent` variants:

```cpp
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` only stops future updates — the client keeps its copy. Use `DestroyReplicatedSubObjectOnRemotePeers` to delete it remotely, or `TearOffReplicatedSubObjectOnRemotePeers` to leave an orphaned local copy. The subobject must override `virtual bool IsSupportedForNetworking() const` to return `true` and declare its own `GetLifetimeReplicatedProps`.

When the flag is false, the engine instead calls the still-live virtual:

```cpp
virtual bool ReplicateSubobjects(class UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags) override;
```

Inside it, forward to `Super::` and call `Channel->ReplicateSubobject(SubObject, *Bunch, *RepFlags)`. Registered subobjects: [replication patterns, Pattern 5](references/replication-patterns.md).

## Physics Replication

`EPhysicsReplicationMode` (`EngineTypes.h`) selects how a simulated body is corrected: `Default`, `PredictiveInterpolation`, `Resimulation`, `None`.

```cpp
SetPhysicsReplicationMode(EPhysicsReplicationMode::PredictiveInterpolation);
EPhysicsReplicationMode Mode = GetPhysicsReplicationMode();
```

`PredictiveInterpolation` and `Resimulation` require Project Settings → Physics → Physics Prediction. Keep every interacting body on the same mode. For rollback-style networked physics use `UNetworkPhysicsComponent` (`Engine/Public/Physics/NetworkPhysicsComponent.h`) and the `FAsyncPhysicsTimestamp` handshake on `APlayerController` (`ClientSetupNetworkPhysicsTimestamp`, `ServerSendLatestAsyncPhysicsTimestamp`); collision and body setup belong to `ue-physics-collision`.

## Iris Replication System

Iris is the alternative replication backend (plugin `Iris`, Beta flag in 5.8; Epic's 5.8 notes call it production-ready for licensees). Runtime module `IrisCore` under `Source/Runtime/Net/Iris`, engine glue under `Engine/Public/Net/Iris`.

- Enable in a module's Build.cs: `SetupIrisSupport(Target);`
- Enable the `Iris` plugin (`EnabledByDefault: false`) and set the runtime switch `net.Iris.UseIrisReplication=1`; it defaults to 0, the classic replication system (`IrisConfig.cpp:14`).
- Property declaration, RPCs, conditions and push model are unchanged. Iris changes the backend, not the gameplay-facing API.

Actor hooks when Iris is active (`GameFramework/Actor.h`):

```cpp
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` and `UObjectReplicationBridge` (`Iris/ReplicationSystem/`) are internal; gameplay code should not derive from them. `UReplicationBridge` no longer has the separate base class it used to; treat it as internal.

## Replication Graph

For high connection counts, replace per-connection relevancy scanning with the ReplicationGraph plugin (Beta in 5.8). Build.cs module: `ReplicationGraph`.

```ini
; DefaultEngine.ini
[/Script/OnlineSubsystemUtils.IpNetDriver]
ReplicationDriverClassName="/Script/MyGame.MyReplicationGraph"
```

```cpp
// 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;
};
```

Node classes (`ReplicationGraph.h`): `UReplicationGraphNode_GridSpatialization2D` (world grid), `UReplicationGraphNode_AlwaysRelevant` (game state, managers), `UReplicationGraphNode_AlwaysRelevant_ForConnection` (controller, player state), `UReplicationGraphNode_ActorList` (hand-built lists), `UReplicationGraphNode_DormancyNode`, `UReplicationGraphNode_DynamicSpatialFrequency`.

## Net Driver and Connections

`UNetDriver` (`Engine/Classes/Engine/NetDriver.h`) owns the connections and drives replication for a world.

```cpp
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`) is one client's connection. Reach it with `AActor::GetNetConnection()` (overridden by `APlayerController`). Split-screen players get a `UChildConnection` (`Engine/ChildConnection.h`) hanging off the parent.

```cpp
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();
```

Prefer `AGameModeBase::Logout` for disconnect handling over polling connection state.

`APlayerController` exists only on the server and its owning client. Data every client needs goes on `APawn`, `APlayerState` or `AGameStateBase` — see `ue-gameplay-framework`.

## Deprecated — do not use

| Do not emit | Use in 5.8 | Source |
|---|---|---|
| `NetUpdateFrequency = X;` | `SetNetUpdateFrequency(X)` / `GetNetUpdateFrequency()` | `UE_DEPRECATED(5.5)` in `GameFramework/Actor.h` |
| `MinNetUpdateFrequency = X;` | `SetMinNetUpdateFrequency(X)` / `GetMinNetUpdateFrequency()` | `UE_DEPRECATED(5.5)` in `GameFramework/Actor.h` |
| `NetCullDistanceSquared = X;` | `SetNetCullDistanceSquared(X)` / `GetNetCullDistanceSquared()` | `UE_DEPRECATED(5.5)` in `GameFramework/Actor.h` |
| `virtual void BeginReplication()` | `OnReplicationStartedForIris` or `FillReplicationParams` | `UE_DEPRECATED(5.7)` in `GameFramework/Actor.h` |
| `virtual void EndReplication(EEndPlayReason::Type)` | `OnStopReplicationForIris` | `UE_DEPRECATED(5.7)` in `GameFramework/Actor.h` |
| `BeginReplication(const FActorReplicationParams&)` | override `FillReplicationParams` | `UE_DEPRECATED(5.7)` in `GameFramework/Actor.h` |
| `UNetConnection::GetConnectionId()` | `GetConnectionHandle()` | `UE_DEPRECATED(5.6)` in `Engine/NetConnection.h` |
| `UNetConnection::SetConnectionId()` | nothing — external code must not set it (`SetConnectionHandle()` is protected, `NetConnection.h:2006`) | `UE_DEPRECATED(5.6)` in `Engine/NetConnection.h` |
| `UNetConnection::GetParentConnectionId()` | `GetConnectionHandle()` | `UE_DEPRECATED(5.6)` in `Engine/NetConnection.h` |
| `UNetDriver::GetConnectionById(uint32)` | `GetConnectionByHandle(FConnectionHandle)` | `UE_DEPRECATED(5.6)` in `Engine/NetDriver.h` |
| `UNetDriver::SetPendingDestruction()` | `RequestNetDriverDestruction()` | `UE_DEPRECATED(5.6)` in `Engine/NetDriver.h` |
| `FPostReplicatedReceiveParameters::bHasMoreUnmappedReferences` | read `OldArraySize` only | `UE_DEPRECATED(5.4)` in `Net/Serialization/FastArraySerializer.h` |
| `UObjectReplicationBridge::DetachInstanceFromRemote` | `DetachRootObjectFromRemote` / `DetachSubObjectFromRemote` | `UE_DEPRECATED(5.8)` in `Iris/ReplicationSystem/ObjectReplicationBridge.h` |
| `UNetObjectFactory::FDestroyedContext` | `FDetachContext` | `UE_DEPRECATED(5.8)` in `Iris/ReplicationSystem/NetObjectFactory.h` |

## Common Mistakes

**Assuming the registered subobject list is on:** it defaults to false, so `AddReplicatedSubObject` alone replicates nothing. Set `bReplicateUsingRegisteredSubObjectList = true` in the constructor (or flip `net.SubObjects.DefaultUseSubObjectReplicationList`) and confirm with `IsUsingRegisteredSubObjectList()`.

**Omitting `Super::GetLifetimeReplicatedProps`:** every inherited replicated property is dropped, including engine state on `AActor` and `APawn`. Call `Super` first, always.

**Mutating replicated state on a client:** the next server update overwrites it and no rollback happens. Guard with `if (!HasAuthority()) return;` and apply authoritative values in `OnRep_`.

**Push model without a marker:** a property declared with `Params.bIsPushBased = true` and never marked dirty simply stops replicating. Every write path needs `MARK_PROPERTY_DIRTY_FROM_NAME`.

**Removing from a fast array without `MarkArrayDirty()`:** removals do not reach clients. `MarkItemDirty` covers mutation only.

**Using `NetMulticast` for persistent state:** late joiners never receive it. Multicast is for one-shot cosmetics; state belongs in a replicated property.

**Server RPC on an unowned actor:** the call is dropped with only a `LogNet` Warning. Call `SetOwner()` on the server after spawning, and keep the chain intact up to the `APlayerController`.

**Non-`UFUNCTION` `OnRep_`:** UHT rejects `ReplicatedUsing` pointing at a plain member function. Declare `UFUNCTION()` above it.

**Server RPC without `WithValidation` that mutates state:** a client can send any parameter values. Validate in `_Validate`, or better, send an id and look up the authoritative data server-side.

**`OnRep_` that is not idempotent:** relevancy changes re-send the full state and re-fire callbacks. Do not treat `OnRep_` as an "exactly once" event.

## Related Skills

- `ue-cpp-foundations` — `UPROPERTY`/`UFUNCTION` specifier reference, module includes, reflection basics
- `ue-gameplay-framework` — `AGameModeBase` (server only), `AGameStateBase`/`APlayerState` replication scope, `APawn` possession
- `ue-gameplay-abilities` — GAS prediction keys, attribute set replication, gameplay effect replication modes
- `ue-character-movement` — CMC move replication, saved moves, server correction and network smoothing
- `ue-actor-component-architecture` — component lifecycle, `SetIsReplicated`, subobject ownership
- `ue-async-threading` — off-thread work feeding replicated state, task graph and async patterns
- `ue-serialization-savegames` — persisting state that outlives a session, `NetSerialize` vs `Serialize`
- `ue-gameplay-tags-messaging` — native and ini gameplay tags, containers, queries and the async message system
- `ue-mover` — the Mover plugin: movement modes, layered moves and rollback networking
- `ue-physics-collision` — collision channels, traces, overlaps and Chaos physics
- `ue-world-level-streaming` — World Partition, level streaming, data layers and travel

© quodsoler · MIT · quodsoler/unreal-engine-skills

Похожие скиллы

Всё по теме «Геймдев и 3D: Unity, Unreal, Godot, Blender» →
game-developer https://github.com/Jeffallan Скилл для разработки игр в Unity и Unreal Engine. Помогает строить системы игровой логики, настраивать физику, многопользовательские сети, шейдеры и оптимизировать производительность до 60+ FPS. CX Codex +1 6 400установок unreal-cpp-gameplay gamedev-skills Учит агента писать геймплейный C++ под Unreal Engine 5: макросы рефлексии, классы Gameplay Framework, зависимости модуля в *.Build.cs. CX Codex +1 5 300установок unreal-engine-cpp-pro sickn33 Скилл для разработки на C++ в Unreal Engine 5.x: правила работы с UObject, сборщиком мусора, отражением и производительностью. CX Codex +1 1 400установок roblox-networking gamedev-skills Скилл для проектирования и защиты клиент-серверной сети в Roblox: RemoteEvent, RemoteFunction, UnreliableRemoteEvent, проверки и лимиты. CX Codex +1 3 500установок godot-multiplayer-networking thedivergentai Скилл для сетевого кода в Godot: транспорт, авторитет сервера, предсказание клиента и отсечение по видимости. Пригодится, когда в игре дёргаются персонажи или клиент жульничает. CX Codex +1 385установок unreal-engine DSTN2000 Скилл обучает ассистента исследовать структуру проекта Unreal Engine перед написанием кода. Он находит файлы .uproject, сканирует ассеты и настраивает C++, Enhanced Input или GAS. CX Codex +1 511установок

Из того же набора25

ue-audio-system Скилл для работы со звуком в Unreal Engine: подсказывает, как проигрывать, микшировать и отлаживать аудио из C++. CX Codex +1 1 100установок ue-serialization-savegames Помогает проектировать сохранение и загрузку игры в Unreal Engine 5.8 на C++, от работы со слотами до бинарной сериализации. Пригодится при настройке USaveGame и снимков акторов. CX Codex +1 1 100установок ue-sequencer-cinematics Скилл для работы с Level Sequences в Unreal Engine 5.8 из C++: запуск катсцен, привязка актёров к трекам, событийные треки и рендер через Movie Render Graph. CX Codex +1 1 100установок ue-ai-navigation Скилл для написания C++ ИИ в Unreal Engine 5.8: контроллеры, деревья поведения, восприятие, navmesh и EQS. Пригодится, когда агент пишет код ИИ и путает API. CX Codex +1 1 100установок ue-gameplay-abilities Скилл для работы с Gameplay Ability System в C++: способности, эффекты, атрибуты, куи и AbilitySystemComponent. Целевая версия — UE 5.8. CX Codex +1 1 100установок ue-physics-collision Помогает настраивать каналы коллизий, трассировки лучей и физику тел в C++ для Unreal Engine 5.8. Пригодится, когда не срабатывает overlap или нужно настроить Sweep-запросы. CX Codex +1 1 100установок ue-procedural-generation Скилл для работы с PCG, рантайм-мешами и инстансингом в Unreal Engine 5.8. Пригодится, когда графы и геометрия строятся кодом. CX Codex +1 1 200установок ue-character-movement Скилл по UCharacterMovementComponent для Unreal Engine 5.8: режимы движения, определение пола, предсказание на клиенте, root motion. CX Codex +1 1 200установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой