What is the best way of replicating this array of structs?

I have an inventory with slots that need to be first replicated then updated in UMG. I’ve managed to make something that kind of works but doesn’t meet all the requirements I have at the bottom.

Situation:

When a player joins I must replicate the entire array to the client. Whenever an entry changes the item struct (which is one integer and one DataAsset reference, currently set to Atomic) needs to be sent over with it’s index (to the owner). I should then in blueprint be able to subscribe to this event (and receive at least the changed index) to update the UI. It would be nice if my blueprint event could receive both the new and old item stack, not required for now though.

Requirements:

  1. Initially replicate the entire item array to owner when they join (and through BP update the UI once it’s received).
  2. At will on the server change an entry in the array, which should be sent to the owning client and they should be notified (similarly to ReplicatedUsing?).
  3. Subscribe through BP to receive the updated information (if possible along with the previous information).
  • The inventory is an Actor Component, and I have its reference in the Widget BP graph, from there I should be able to subscribe to the updates if the client owns the inventory component.
  • I also of course don’t want the information to be accidentally sent over the network twice via the Blueprint event, it should either be the same event or preferably a separate client side only event (so that it can provide additional information).

Thanks very much in advance!

2 Likes

I was able to answer it by experimenting myself. For any future readers I will explain the system.

  • I use regular replication for the array, as it seems Unreal optimized and doesn’t send over the entire array when one item changes (UPROPERTY(Replicated, ReplicatedUsing=OnRep_AFunctioName))
  • I have the replication condition COND_OwnerOnly to make use only the owner is aware of the inventory
  • I have a multi cast delegate which sends over information to the UI (where I bind it to a function)

The main issue I had previously is that I wasn’t aware the array replication was optimized, so I had clumsy workarounds.

The only flaw is that I do not get informed of which array indexes have updated and have to loop through and compare which is O(N) rather than O(1). It’s fine for my use case with only a dozen or so indexes. For this reason I’m still accepting a better answer which solves this flaw, so thanks in advance once again!

3 Likes

Hey @Sezze!

I know your question is a couple of years old, but I have a better solution to this issue

So, what solution am I talking about?

  • Fast TArray replication (namely FastArraySerializer).
  • Tada! :smiley:
  • Spoiler: It does come with a few drawbacks

The pros:

  • Changing or deleting an element somewhere in the middle of the array does not instigate the replication of all the elements following the changed/deleted element.
  • One of your requirements: It allows events to be called on the Client when an element changes
  • Perfect for large datasets

The cons:

  • Elements which change have to be marked dirty explicitly
  • This could be a deal breaker: The order of elements in the array is no longer guaranteed to be the same on both the client and the server

How can you implement it?

  • See FastArraySerializer.h for detailed instructions in the Engine source code

Hope this helps!

2 Likes