void AMyGameMode::Tick() {
if (whatever) {
A = GetWorld()->SpawnActor<AMyActor>(/*...*/ bDeferConstruction = true);
A->MyProperty = 42;
A->FinishSpawning()
}
then when the AMyActor instances spawn from replication on the clients, is MyProperty guaranteed to be set to 42 before their BeginPlay is called?
That is, are the initial properties contained in the same message that instructs the clients to spawn the replicated actor? Or is it possible they could come later in a separate message after the BeginPlay of the replicated actor has already been called?
After studying the code I think I’ve figured out that it is guaranteed. Bunches (unreal network messages) are sent via UActorChannels. When a new (bReplicates=true) actor is spawned on the server the following happens on the client:
A UActorChannel is created with Actor=NULL
The server prepares the initial bunch. An initial bunch contains both the spawn info and initial properties. (See “An ActorChannel bunch looks like this” in ActorChannel.h)
Each bunch (including the initial bunch) is processed by one call to UActorChannel::ProcessBunch
UActorChannel::ProcessBunch does (essentially) the following:
if (Actor == NULL) // this is the initial bunch
{
bSpawnedNewActor = true;
Actor = SerializeNewActor(/*...*/); // Calls NewObject<Actor>
}
while (/*...*/)
Replicator->ReceivedBunch(/*...*/); // Read properties and rpcs
if (Actor && bSpawnedNewActor)
Actor->PostNetInit(); // calls BeginPlay
So for the initial bunch all three parts of that code are active. NewObject is called to create the replicated actor, its initial properties are set, then PostNetInit is called on it which calls BeginPlay
What about UActorComponent, because sometimes it’s not guaranteed, different behavior. Also, if call RPC to/in that component on creation, then property with COND_InitialOnly will never be replicated.