UE 5.7 (Source/Dist) Configuration
The following steps are needed to use Iris:
In unreal editor enable Iris Networking (Beta) Plugin ( Restart)
Update UProject
Check that the plugin has been added to uproject file
"Plugins": [
...
{
"Name": "Iris",
"Enabled": true
}
}
Build.cs Modules
For each module using replication in the project add the following to the build.cs file.
public VirtuosoWorlds(ReadOnlyTargetRules Target) : base(Target)
{
SetupIrisSupport(Target);
...
}
DefaultEngine.ini
[SystemSettings]
net.SubObjects.DefaultUseSubObjectReplicationList=1
net.Iris.UseIrisReplication=1
[Core.Log]
LogIris=VeryVerbose
LogIrisReplication=VeryVerbose
Confirmation
The following shows a successful startup of Iris in the Server Logs
[2025.12.12-09.12.34:996][ 0]LogPluginManager: Mounting Engine plugin Iris
...
[2025.12.12-09.12.34:997][ 0]LogConfig: Set CVar [[net.Iris.UseIrisReplication:1]]
...
[2025.12.12-09.12.48:764][904]LogCsvProfiler: Display: Metadata set : iris="1"
Fast Arrays
In traditional Unreal replication:
-
TArray replication sends the entire array every time something changes.
-
Large arrays (inventory items, projectiles, etc.) are inefficient and generate a lot of network traffic.
Iris Fast Arrays solve this:
-
Server authoritative by default ( Replicate from server to client )
-
They replicate changes incrementally instead of the whole array.
-
They track added, removed, and modified elements automatically.
Why MarkItemDirty() Exists
-
FFastArraySerializertracks which items changed since the last network update. -
Without marking an item dirty, Iris has no way of knowing it was modified, so it won’t replicate that change.
-
This is how Iris sends only incremental changes, rather than the whole array.
Purpose of operator==
-
Iris/FFastArraySerializer uses
operator==internally to check if an item has changed since the last replication. -
If the item appears “equal” to the old version, it won’t be replicated.
-
If the item is different, Iris marks it for replication.
Without operator==, Iris has no reliable way to detect changes, and you may see updates not being sent to clients.
Inspector Properties Support
To ensure that the fast array shows up in the inspector details we do the following
# InventoryItem.h
UPROPERTY(EditAnywhere, meta=(ShowOnlyInnerProperties))
TArray<FInventoryItem> Items;
...
# MeshActor.h
UPROPERTY(Replicated, EditAnywhere)
FInventoryArray Inventory;
# InventoryItem.h
#pragma once
#include "Net/Serialization/FastArraySerializer.h"
#include "InventoryItem.generated.h"
USTRUCT()
struct FInventoryItem : public FFastArraySerializerItem
{
GENERATED_BODY()
UPROPERTY()
int32 ItemID;
UPROPERTY()
int32 Quantity;
// Checks if an item has changed since last replication
bool operator==(const FInventoryItem& Other) const
{
return ItemID == Other.ItemID && Quantity == Other.Quantity;
}
};
USTRUCT()
struct FInventoryArray : public FFastArraySerializer
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, meta=(ShowOnlyInnerProperties))
TArray<FInventoryItem> Items;
bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms)
{
return FastArrayDeltaSerialize(
Items, DeltaParms, *this
);
}
// Helper functions to safely add items
void AddItem(FInventoryItem NewItem)
{
Items.Add(NewItem);
MarkItemDirty(Items.Last());
}
void UpdateItem(int32 Index, int32 NewQuantity)
{
if (Items.IsValidIndex(Index))
{
Items[Index].Quantity = NewQuantity;
MarkItemDirty(Items[Index]);
}
}
};
# MeshActor.h
#pragma once
#include "CoreMinimal.h"
#include "InventoryItem.h"
#include "GameFramework/Actor.h"
#include "Net/UnrealNetwork.h"
#include "MeshActor.generated.h"
UCLASS()
class AMeshActor : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(Replicated)
int32 ItemID;
UPROPERTY(Replicated)
float Durability;
UPROPERTY(Replicated, EditAnywhere)
FInventoryArray Inventory;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMeshActor, ItemID);
DOREPLIFETIME(AMeshActor, Durability);
DOREPLIFETIME(AMeshActor, Inventory);
}
};
How clients can “update” the server safely
Use Server RPCs (UFUNCTION(Server, Reliable)):
UFUNCTION(Server, Reliable)
void ServerAddItem(int32 ItemID, int32 Quantity);
Implementation:
void AVWPlayerCharacter::ServerAddItem_Implementation(int32 ItemID, int32 Quantity)
{
FInventoryItem NewItem;
NewItem.ItemID = ItemID;
NewItem.Quantity = Quantity;
Inventory.AddItem(NewItem); // MarkItemDirty called internally
}
-
Client calls
ServerAddItem(ItemID, Quantity) -
Server adds the item and marks it dirty
-
Iris replicates the change to all clients, including the one that requested it
This is the correct server-authoritative flow.