Why is the BeginPlay event is delayed in clients?

Hey everyone!

We are developing a four player game where the player color is set in the BeginPlay event in our actor blueprint. The event is delayed greatly (meaning 3+ minutes) in our clients before it runs. During the time before it is set the players can move about and then suddenly the event is called and a color is set.

Is the BeginPlay event delayed until background networking is established between the client and server?

Our level is filled with objects active for replication, the count being around 400 right now and it will rise in the future. We have tested the delay with an empty level and it is almost instant.

Is there a way to reduce the delay by network priority or by ignoring “network establishment” before running BeginPlay?

You could try manipulating this from the AActor class.

“Priority for this actor when checking for replication in a low bandwidth or saturated situation, higher priority means it is more likely to replicate”

UPROPERTY(Category=Replication, EditDefaultsOnly, BlueprintReadWrite)
float NetPriority

I made an attempt to find possible values for this variable with no luck. I would guess either 0.0f - 1.0f or 0.0f - 100.0f with the higher value being higher priority. My guess would be 0.0f - 1.0f.

I see this question was many years ago, but I’m investigating something similar (in UE 4.26.2) - occasionally some clients will join a game (or after non-seamless-travel) and execution of Event BeginPlay on all actors, including Pawns, PlayerControllers, etc., is delayed for up to 1 minute on that client.

I can partially answer this:

Is the BeginPlay event delayed until background networking is established between the client and server?

At least for non-seamless travel, clients won’t execute BeginPlay on anything until they receive the GameState. Once they do, in particular when the AGameStateBase::bReplicatedHasBegunPlay variable replicates over to a client, AGameStateBase::OnRep_ReplicatedHasBegunPlay() calls AWorldSettings::NotifyBeginPlay(), which then calls AActor::DispatchBeginPlay() on everything in the world, and causes e.g. blueprint Begin Play events to run on the client.

GameState has a default NetPriority of 1, so I think what might be happening in my situation is heavy network traffic on the pawns (NetPriority 3) is starving the GameState from replicating (??).

GameState has a default NetPriority of 1, so I think what might be happening in my situation is heavy network traffic on the pawns (NetPriority 3) is starving the GameState from replicating (??).

Some more notes on debugging our particular issue: I’m reproducing it with 4 clients; 2 of them work as expected, and 2 will not receive the GameState for about a minute.

What I’m seeing with adding some specific logging to UNetDriver::ServerReplicateActors is NumClientsToTick is 2 (we have NetClientTicksPerSecond = 200), so we’re only ticking 2 clients at a time. The GameState never ends up on the “bad” clients’ ConsiderList for the entire minute. It does end up on the ConsiderList for the “Good” clients, and is sent to them. The GameState is marked as not needing to be sent again for 100ms. When that time elapses, the same two “Good” clients are the ones being considered by UNetDriver::ServerReplicateActors which I guess is what causes our problem.

Because the GameState never ends up on the ConsiderList for the “bad” clients, the NetPriority is irrelevant (that would only come into play if it’s added to the ConsiderList.)

It looks like there is some code in ServerReplicateActors meant to handle this case, marked with the comment // then mark each considered actor as bPendingNetUpdate so that they will be considered again the next frame when the connection is actually ticked but I’m not sure why it’s not working in my case.

As a workaround, we’re going to try calling ForceNetUpdate on GameState every frame, as long as there are player controllers on the server for which BeginPlay hasn’t run on the corresponding client yet.