Quick answer: UObject subobjects do not replicate automatically. Override ReplicateSubobjects on the owning actor and call Channel->ReplicateSubobject for each subobject. Set the subobject’s Outer to the actor and mark replicated properties with UPROPERTY(Replicated).

You build an inventory system where each player has a UObject-based Inventory with UObject Items inside. It works perfectly on the server, but clients never see the items. ActorComponents would have replicated for free; UObjects need manual wiring.

Why UObjects Don't Replicate Automatically

Unreal’s replication system is built around Actor channels. Each replicated Actor has a channel and streams property updates through it. ActorComponents piggyback on the parent actor’s channel. UObjects have no channel and no automatic hookup — you have to tell the actor to include them in its replication bunch.

The Four-Part Setup

Step 1: Construct the subobject with the actor as Outer.

// In the actor's constructor or BeginPlay
Inventory = CreateDefaultSubobject<UInventory>(TEXT("Inventory"));
// Or at runtime:
Inventory = NewObject<UInventory>(this);

Step 2: Override ReplicateSubobjects on the actor.

bool AMyPlayer::ReplicateSubobjects(UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
    bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
    if (Inventory)
    {
        WroteSomething |= Channel->ReplicateSubobject(Inventory, *Bunch, *RepFlags);
        for (UItem* Item : Inventory->Items)
        {
            if (Item)
                WroteSomething |= Channel->ReplicateSubobject(Item, *Bunch, *RepFlags);
        }
    }
    return WroteSomething;
}

Step 3: Mark replicated properties on the subobject.

// In UInventory
UPROPERTY(Replicated)
TArray<UItem*> Items;

void UInventory::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);
    DOREPLIFETIME(UInventory, Items);
}

bool UInventory::IsSupportedForNetworking() const { return true; }

Step 4: The owning actor must replicate. Call SetReplicates(true) in the actor constructor or set bReplicates in the class defaults. Without it, the actor channel never opens and subobject replication is irrelevant.

Common Mistakes

Verifying

Enable Net.Log=Verbose in DefaultEngine.ini and watch the log during PIE. You should see NetGuid Allocated for each subobject and Bunch Written entries for property updates. If you never see the subobject, the Outer or ReplicateSubobjects hookup is wrong.

“UObject replication is four lines of boilerplate, but missing any one of them produces silence. Use ActorComponents where you can, UObjects where you must.”

Related Issues

For replicated variable problems on ActorComponents, see Unreal replicated variable not syncing. For listen server quirks, see Unreal replicated function not called on listen server.

Prefer ActorComponents. If you need UObject subobjects, write the ReplicateSubobjects override before anything else.