Hello,
I’m having an issue with getting a TArray of custom ItemObjects to replicate after the initial client load (it does when a client loads, but does not replicate after that). I am successfully adding ItemObjects to the TArray within the InventoryComponent on the server, but it does not replicate to clients. That is to say, the server’s edition of the TArray contains the ItemObject while the client’s does not, and no replication occurs.
I’m slowly learning UE and networking so correct me if I’m wrong, but I thought the proper approach to an inventory system like this would be to have the server add the item to the inventory, and update the clients via replication. Perhaps I somehow have to manually tell the server to replicate and it does not automatically detect the change in the array?
Anyway, here’s my setup. I have aggressively thrown in the “Replicated” UPROPERTY specifier even if I’m not sure I need it in case that was the issue:
I created UItemObject’s that are derived from UObjects. They just have some basic additional data and are not too complicated:
UCLASS(Blueprintable)
class UItemObject : public UObject
{
// GENERATED BODY and some stuff above, example property here:
private:
UPROPERTY(meta=(ExposeOnSpawn), BlueprintGetter=GetDimensions, Replicated)
FIntPoint Dimensions;
public:
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty> & OutLifetimeProps) const override;
};
void UItemObject::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UItemObject, Dimensions);
}
I created a UInventoryComponent that is derived from UActorComponent that contains a replicated TArray of UItemObject*s. The ReplicatedUsing callback function just prints to screen for debugging so I can see when replication occurs:
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent), Blueprintable)
class UInventoryComponent : public UActorComponent
{
public:
// TODO: Add Anti-Cheat with "Validation"
UFUNCTION(Server, Reliable, BlueprintCallable)
void ServerTryAddItem(UItemObject* ItemToAdd);
protected:
UPROPERTY(BlueprintReadWrite, ReplicatedUsing=TempCheckReplication)
TArray<UItemObject*> Items;
public:
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty> & OutLifetimeProps) const override;
};
void UInventoryComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UInventoryComponent, Items);
}
As of now, the InventoryComponent is only added to a AMainCharacter C++ class that is derived from ACharacter. AMainCharacter has a replicated InventoryComponent added to it:
UCLASS()
class AMainCharacter : public ACharacter
{
public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Components, meta = (AllowPrivateAccess = "true"), Replicated)
TObjectPtr<class UInventoryComponent> InventoryComponent;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty> &OutLifetimeProps) const override;
};
AMainCharacter::AMainCharacter()
{
InventoryComponent = CreateDefaultSubobject<UInventoryComponent>("InventoryComponent");
}
void AMainCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty> &OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMainCharacter, InventoryComponent);
}
Any advice would be appreciated, I feel as though I need something as simple as marking the InventoryComponent dirty for replication, or that I’m missing some other function override like GetLifetimeReplicatedProps that’s necessary for replication that I can’t seem to find.
I’ve also taken a look at Replicating custom subobject which is UPROPERTY of ActorComponent but there doesn’t seem to be an updated solution there.
In the mean time, I’m reading up on replication and seeing what steps I’ve missed, and reading through https://jambax.co.uk/replicating-uobjects/.