Is there an extra trick to replicating actor references?

I have a UObject subclass with replication support implemented (as described here and in the wiki), which is working great. I have a number of UObject derived classes replicating just fine. However, I have one UPROPERTY that I can’t get replicating. It’s of type AActor*, referencing an actor that was spawned at runtime in Blueprints using the Spawn Actor node. The actor’s owner is set the same as the UObject containing the replicated property (which is an actor component on the game state).

Other properties on the object replicate correctly, but the actor reference is always None on the client. It’s being assigned on the server, and I’ve verified it’s assigned correctly. For some reason, though, the UPROPERTY (and only this one) wont replicate.

Do I have something different / extra when replicating an actor reference?

Here’s the relevant code:

Item.h:

    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
    virtual bool ReplicateSubobjects(UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags) override;

UPROPERTY(Replicated, BlueprintReadOnly, Category="Inventory")
AActor* ItemActor;

Item.cpp:

void UItem::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(UItem, ItemActor);
    ...
}

bool UItem::ReplicateSubobjects(UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
    bool bWroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
    if (ItemActor)
    {
        bWroteSomething |= Channel->ReplicateSubobject(ItemActor, *Bunch, *RepFlags);
        bWroteSomething |= ItemActor->ReplicateSubobjects(Channel, Bunch, RepFlags);
    }
    ...
    return bWroteSomething;
}

An additional bit of detail: the UItem class represents an inventory item; the actor is being spawned when an item is equipped, and is immediately attached to a socket on the player pawn mesh. I believe that means it should automatically become a default sub-object of the player actor, and I originally set its actor to the player character for that reason.

The actor itself is correctly replicating regardless of whether I set its owner to the UItem instance or the player character actor (maybe because the the ownership is overridden by the AttachActorToComponet BP node?). I’m not storing a reference to the actor anywhere else but on the UItem instance, though, so if that reference doesn’t replicate I can never get a reference to the actor again :-}

overriding

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

should not be necessary,
is the object you are spawning set to being replicated?

How object pointers in unreal networking work are that they are sent to the client, which then has to figure out what the local object is that the pointer is pointing to, if the object does not exist because e.g. no replication, unreal will set the pointer to nullptr

The actor is replicated, and is visible both on the listen server and on clients.

I thought the call to ItemActor->ReplicateSubobjects(...) may be redundant / unnecessary but what about the Channel->ReplicateSubobject(ItemActor, ...) call? Should that be needed to replicate the pointer? It’s still not entirely clear to me when that needs to be there explicitly (especially given that my UItem is derived from a replication enabled UObject subclass, not from AActor).

No should not be necessary for vanilla pointer replication if you want special behavior on certain reactions then you might need to override, but if you just want the client and the server to point to the same thing, no additional work other than.

Making the actor replicated and setting the pointer to replicated is necessary.

Hmm, I’ll have to try without that and see what happens. Thanks for the info on how it should be working!