Download

If I spawn something on the server, how do I know that it is ready on the client?

I have created an RtsPawn which spawns a character on the server and replicates the character to the client. I also have a PlayerController which possess the RtsPawn. Now I want to bind some functions from the spawned character to player input.
The problem that I have is that I do not know when the character is ready on the client. I think I could do it like this:


class AArenaCharacter* OldServerCharacter;
UPROPERTY(ReplicatedUsing=OnRepServerCharacter)
class AArenaCharacter* ServerCharacter;

void RtsPawn::OnRepServerCharacter{
   if(OldServerCharacter == nullptr && ServerCharacter != nullptr){
      //ServerCharacter just got replicated this first time, client should be ready
   }
   OldServerCharacter = ServerCharacter;
}

This is a bit ugly, are there other ways to do this? Maybe I could send a ClientRpc from the server with the SpawedCharacter?



UFUNCTION(Client,Reliable)
void ClientSpawnedCharacter(AArenaCharacter* SpawnedArenaCharacter);

How would you do this?

The “BeginPlay” method is called on the Server and on the Client. Just use something like this:



if(Role < ROLE_Authority)
{
    DoClientCodeOnBeginPlay();
}

in the BeginPlay of the Actor.

This is what I am doing in the BeginPlay function


	if (HasAuthority()) {
		ServerCharacter = Cast<AArenaCharacter>(GetWorld()->SpawnActor(ServerCharacterClass));
		ServerCharacter->SetActorTransform(GetTransform());
		PlayerAI = GetWorld()->SpawnActor<AAIController>();
		PlayerAI->Possess(ServerCharacter);
		ServerCharacter->SetOwner(this);
	}

But ServerCharacter is null when SetupInputComponent is executed on the Client. It first needs to replicate which takes some time I guess.


InputComponent->BindAction("Spell1", IE_Pressed, ServerCharacter, &AArenaCharacter::CastSpell);

Ah yes, it takes time. For this you can really only use the “OnRep” functions. Or you simulate things on the client, like filling the variable on his side
too, so he doesn’t feel the lag.

Maybe I could spawn a thread on the client that just checks if the Servercharacter is not null, calls some function and terminates? For example



//Thread
while(true){
    if(ServerCharacter){
        OnClientReady();
        break;
    }
}

If you only want to know when the Client Version of the Variable gets the value, you just need to use the OnRep function.
It is called on the client, as soon as the variable got the value that the server set it to. Other things will just be dirty work arounds.

I only want to know when the client gets the variable the first time, so I can bind my actions to it. OnRep doesn’t really help.

I have now created my own TickEvent which broadcast every tick, then I subscribe a function to it like so


 
void WaitForServerChar{
   if(ServerCharacter){
        OnClientReady();
        UnsubscribeFromTickEvent();
    }
}

OnTick().AddDynamic(this, &WaitForServerChar);



And then I do my binding in the OnClientReady function.


void Foo::OnClientReady{
    InputComponent->BindAction("Spell1", IE_Pressed, ServerCharacter, &AArenaCharacter::CastSpell);
}