We’re using FFastArraySerializer to store data about our actors in the world. The array is quite large, but it is mostly static. It is initialized and replicated once at game startup, and only updated occasionally when characters spawn or despawn.
When an element is removed, we:
- Remove its associated data from the FFastArraySerializer array.
- Call FFastArraySerializer::MarkArrayDirty() as per the documentation.
What we see in Network Insights, whenever we remove an element, is that the entire array is re-replicated rather than just sending the delta. Given the array’s size, this has a significant bandwidth impact. I would expect replication to only send a minimal payload, ideally just the ID or index of the removed element without re-sending unchanged entries.
Questions:
- 1. Is this the intended behavior for element removals in FFastArraySerializer, or is this a bug?
- 2. Are there best practices for handling large, mostly-static datasets with occasional removals?
- 3. Would you recommend avoiding FastArrays entirely for this type of data structure?
Unreal Version we’re on: 5.5.4
Hi,
This is definitely unexpected behavior, and this use case of a large, infrequently changing array is generally when we’d recommend using fast arrays. Fast arrays do not maintain the same order between the clients/server, and one of the main benefits of doing so is that it can avoid needing to resend the whole array when one element is added/removed.
One possibility is that the removal is updating some data on the other array elements somehow, or that data in the array elements is being changed without them being dirtied, causing them all to be sent at once when the array is dirtied.
Are you able to reproduce this issue in a basic sample project? In my own test project, I am still seeing the expected behavior where only the removed element is replicated.
Thanks,
Alex
Good to know that its something we’re doing wrong on our end. We have several FastArray’s and all of them suffer from the same issue.
We are also using Iris, which I forgot to mention. I noticed there is a FIrisFastArraySerializer, so I tried to inherit from that but it didnt change anything.
I also took a look at GAS and the ActiveGameplayEffects in MixedMode (to see how gameplay effects are replicated to the owning client) and it replicated the removal exactly how I expected it should be removed, with very little data. And this is running in our project as well, so it must be something we’re doing wrong with our implementation.
[Image Removed]
So its definately something we did wrong with our FastArray implementation. But its pretty unclear what that would be. Two of us have been using the exact instructions written in FastArraySerializer.h and both implementations suffer from the same issue. while GAS’s ActiveGameplayEffects does not
The final thing we tried is disabling Iris (net.Iris.UseIrisReplication=0) and that actually fixed our problem. So there is something up with Iris and FastArrays, but we cant see anything in our implementation that GAS _is_ doing that we’re not that could cause this…
Thank you! that solved our problem! and indeed we noticed what you saw where multiple items are re-replicated when we remove.
Hi,
Thank you for the additional information! In Iris, RemoveAtSwap should always be used to remove items from a fast array, as this should prevent other elements from being replicated unnecessarily. I’ve made a note to include this information in our documentation or in some other public-facing article.
It is also worth noting that Iris uses a 64 bit changemask for its fast arrays. Because of this, modifying a single element can cause a number of elements (equal to the array’s size divided by 64) to be replicated, so you may still see more than one item replicated when removing/changing a single fast array item.
Thanks,
Alex