I believe this is the buffer limit being overflowed on Reliable calls for a particular Actor. We are using an ECS system to manage many Entities outside of the Actor system but using 1 Actor to manage them all.
The problem is that Unreal doesn’t see this Entities as Actors and the networking component is on the Player Controller so essentially we could have 100 entities but all piped through 1 Actor network component which severely limits the capacity.
I’m looking for some help in getting around this limitation or some pointers into looking into using another tactic so achieve a more realistic limit. Any help or tips would be most appreciated.
You need to reconsider your approach, and move away from relying on RPCs.
Exceeding the reliable packet limit yields a different message. It’s more likely you’re just packing way too much data into each RPC, and are exxeeding the max allowable size of the bitstream. The limits are there for a good reason, bypassing or changing them in engine code would be a mistake IMO.
The first port of call should be eliminating RPCs to perform stateful updates anyway. Persistent changes to the state of an object should always be done in the form of replicated properties. RPCs for events, properties for State - this is the golden rule of replication.
The way to make this approach scale, is to create multiple actors that serve as proxies for batches of entities. You will not be able to update every entity in lockstep with others, or in the same network packet. They will all be updated at different times and intervals like normal actor replication - but the system needs to be tolerant of that to ever work in a networked game anyway.
Note that clients will be kicked when their reliable buffer overflows. This is essential in order to garauntee that reliable packets are executed in the order they are called (within each actor), and note that this system can also induce additional latency for reliable calls if packets are dropped.
You could also consider using MASS, which is the engines own take on an ECS system and has some primitive replication support. The replication system wasn’t really designed to work with ECS though, so it’s difficult to reach an optimal solution.
Yeap, we’re certainly exceeding the limit for RPC calls and it’s understandable why with 1 Actor managing so many pseudo-Actors (Entities).
I totally understand the limits are there for good reason, it’s just our 1 Actor is essentially wanting to be 100 or 1000 ‘Actors’ in the form of Entities. Since Mass Replication isn’t currently there yet to be used, we’re essentially managing these Entities using one AEnemySpawner Actor. We really wanted to use Mass but the help for it and lack of clarity on what works and on which platform make it really difficult. Documentation as always, hugely lacking.
The biggest challenge is a player joining and then needed to sync a bunch of FVector locations. I’ve looked into spawning multiple Actors to essentially ‘parallelise’ the calls but Actors are really heavy and doesn’t feel right if you know what I mean.
I noticed you made a blog on UObjects which are much lighter than Actors - could that also be a method?
This is exactly why you should use property replication for state and not RPC’s. Join-in-progress “just works” so long as you stick to that rule and you don’t have to do anything extra. This also extends to other concepts like network relevancy and dormancy. It’s critical that state is driven through properties.
Actors are the only engine type that support any form of gameplay networking. UObject/Actor Component replication piggybacks off of its owning actor and adds additional overhead to each packet to identify it, so if anything it’d make the problem worse.
The other problem you have with using a single actor is that all entities will be always-relevant and updating at the same frequency - so you can’t benefit from concepts like relevancy or adapative replication frequency for optimisation and/or bandwidth saving.
The engines core networking model is built for and optimised around the actor/component paradigm rather than ECS approaches, so anything that wants to use it has to piggyback off of that model and is usually going to be sub-optimal. This includes mass btw.
I’m not advocating RPCs to use. I’m just exploring the options. If we were to sync the starting locations of 1000 enemy, using replication - this would be a TArray of 1000 FVector_NetQuantize or something like that set as a Replicated property. Is this method unreliable behind the scenes but taken care of for us? (Eventually consistent?).
The Actor who owns the enemy is not expected to keep their locations in sync (although the spawning event will need to be coordinated) - we’re looking to replicate the Shepherds, not the Sheep in this respect - i.e keep targets in sync and use a consistent flow field on clients to keep them pathing when not pathing to a player.
Since this is very bespoke, I’ll also explore web sockets and a server method too.
Just want to extend my thanks. I’ve settled on using FFastArraySerializer and optimising data transfer. For anyone else, I would advise checking out the use of FFastArraySerializer in the Lyra project.