Quick answer: Make sure you override GetLifetimeReplicatedProps and call DOREPLIFETIME_CONDITION for the right property. Verify the actor has an owning PlayerController for COND_OwnerOnly to work.

You added a private inventory array to a player’s pawn and used DOREPLIFETIME_CONDITION(AMyPawn, Inventory, COND_OwnerOnly) to keep it from leaking to opponents. Open a 4-player session, log Inventory contents from each client — every client sees every player’s inventory. The condition is being ignored.

How Replication Conditions Work

Each replicated property has a per-frame check the engine performs against every connection. COND_OwnerOnly resolves “owner” via AActor::GetNetOwner, which walks up the owner chain to a APlayerController. If the actor has no owning PlayerController, “owner” is the server (or null), so the engine sends the property to nobody — or to everyone, depending on the condition.

Common ways to break this:

Step 1: Correct Replication Registration

// MyPawn.h
UCLASS()
class AMyPawn : public APawn
{
    GENERATED_BODY()
public:
    AMyPawn() { bReplicates = true; }
    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const override;

protected:
    UPROPERTY(Replicated)
    TArray<FName> Inventory;
};

// MyPawn.cpp
void AMyPawn::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const
{
    Super::GetLifetimeReplicatedProps(Out);
    DOREPLIFETIME_CONDITION(AMyPawn, Inventory, COND_OwnerOnly);
}

The const override on the function signature must match exactly — if it’s missing override and the parent signature changes, your method silently stops being called.

Step 2: Ensure Server Owner Is Assigned

When the player spawns, the server assigns the pawn to the PlayerController via possession. Verify with a log:

// On the server, after spawn
APawn* P = ...;
P->SetOwner(PlayerController);
UE_LOG(LogTemp, Log, TEXT("Pawn owner: %s"),
       P->GetOwner() ? *P->GetOwner()->GetName() : TEXT("none"));

If the log says “none”, the PlayerController didn’t take ownership. Without ownership, COND_OwnerOnly excludes the property from every client — including the one you intended to send it to. In practice this often means the inventory looks empty on all clients, which is the inverse of the original bug.

Step 3: Confirm the Condition Macro

Common confusion table:

Step 4: Use Network Profiler

From the console on the server:

NetProfile start
// play for 30s
NetProfile stop

Open the saved profile in Tools → Profiling → Network Profiler. You’ll see per-property bandwidth and per-connection deltas. If Inventory shows up under more clients than expected, the condition isn’t being honored.

Verifying

Add a log to OnRep_Inventory and run 4 clients. Only the owning client should log inventory contents. Other clients should never call OnRep. If they do, double-check ownership and condition setup.

“Replication conditions need three correct things: registration, ownership, and the right macro. One missing piece = condition ignored.”

For player-private data, COND_OwnerOnly + SetOwner is the safe combination. Verify owner is set before any replication starts.