Download

DOREPLIFETIME prevents bReplicatesMovement, but both work on their own.

Yet another question about network replication.

So far in my project, simple variable replication like the following hasn’t been a problem:



.h


UPROPERTY(Replicated)
		int32 networkId;

.cpp

void APuzzleBlankBlock::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
	DOREPLIFETIME(APuzzleBlankBlock, networkId);
}



Whenver I run this with 4 Players I can see that the client’s variable will be set to the server’s value, whenever that server changes it. Perfect.

Seemingly unrelated to this, my Actor can also replicate it’s movement and rotation, however much easier, through setting the inherited “bReplicatesMovement” field to true. This, also,
works like a charm on its own. The Actor in both cases is obviously set to “bReplicates = true” as well, and appears in all other clients’ viewports.

However, combining these too stops the movement and rotation from being replicated alltogether, all Actor’s are still visible, barely moved away from their spawn, and
not moving at all. The replicated variable “networkId” continues to work. I do have the suspicion that the DOREPLIFETIME is used to replicate the movement and
rotation as well, since that’s how I would do it if I didn’t have the simple boolean, so I might be overwriting the code that replicates these. I imagine there’s a replication of the
location Vector and the rotation Rotator with both having a RepNotify with setting these variables when changed. But I am too noob to find the exact setup that lets me
have both variable replication and automatic movement/rotation replication. I imagine this problem must have come up rather often, but I couldn’t find anything in the forums either.
Any tips on this would be greatly appreciated, my project deadline is coming up and I’d hate to spend time on coding location/rotation replication from hand.

Cheers!

EDIT: SOLUTION

GetLifetimeReplicatedProps needs to call it’s super even though this is barely mentioned anywhere! :slight_smile: Be aware!



void AActorClass::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(AActorClass, yourVariableToBeReplicated );
}


Thanks again to everyone being incredibly helpful.

Hey juggle, you must also do a call to the Super class’ GetLifetimeReplicatedProps. That should solve your problem!



void APuzzleBlankBlock::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(APuzzleBlankBlock, networkId);
}


This.
It’s not documented and yet so important.

Oh thank you! It does work parallel, the super call isnt mentioned in this tutorial and even though it works for one variable,
whenever I try this: … it doesnt work reliably.



void APuzzleBlankBlock::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(APuzzleBlankBlock, networkId);
        DOREPLIFETIME(APuzzleBlankBlock, healthPoints);
        DOREPLIFETIME(APuzzleBlankBlock, lifeTime);
}


Sometimes my variables are simply NULL on the Client, and weirdly Client #3 can do everything fine, whereas Client #1 and #2
do not get the replicated values…
Any ideas on this?

Where are you setting up the values?

The server calls setter functions on the Actor, it’s my “carddeck” class that has 40 objects of type APuzzleBlankBlock, they are all spawned there and eventually the deck calls " setHealthPoints" etc. That should change the value of the server object and through replicate also change on the client, right? It works with a single variable but somehow adding more ( in the exact same way, UPROPERTY(replicated) etc. ) sometimes works and sometimes not… I then have a server RPC on the APuzzleBlankBlock that is called whenever the client card is clicked, that one looks like this:



puzzleblankblock.cpp
void APuzzleBlankBlock::BlockClicked(UPrimitiveComponent* ClickedComp)
{
	if (Role != ROLE_Authority) if (PlayerController) PlayerController->ServerBlockClicked(this);
}


playercontroller.cpp

void APuzzleBlankPlayerController::ServerBlockClicked_Implementation(APuzzleBlankBlock* card){
	 APuzzleBlankGameMode* gameMode = Cast<APuzzleBlankGameMode>(GetWorld()->GetAuthGameMode());
	 if (gameMode) {
		 UE_LOG(LogTemp, Warning, TEXT("Client called server's cardClicked %d"),card->GetIndex());
		 gamemode->myStateMachine->cardClicked(card);
	 }
}


and “cardClicked” in “myStateMachine” should now know which card was clicked on the client, right? Like I said, works with Client #3, not the other two…

Oh but I did workaround this nicely I think. Instead of passing the Pointer to my card object ( which I believe was doing the shenanigans ) I instead pass my card’s index, which allows me to easily find it on the server and do everything with the actual server object. I’m pretty happy about this, except the fact that I cannot differentiate my clients. I imagine I can simply get an ID somewhere? Either way, glad this was resolved nicely!