Pawn movement not replicated to client

I have a simple test project.

I start the multiplayer game with two pawns (not characters) for two players to control. Each one has their own window in PIE (listen server)

The client reads an input button and sends a movement vector to the server through an RPC.

The server moves the pawn correctly. With the two windows in PIE I can see the pawn moving in the server version (listen server), but in the client the pawn doesn’t move.

The Pawn BP has Replicates, Net Load on client, Replicate Movement, and Always Relevant Checked.

Any ideas what I’m missing?

The RPC:

UFUNCTION( Server, WithValidation, Unreliable )
void Client_SendMovementToServer(FVector ReqMovement);

void ATestPawn::Client_SendMovementToServer_Implementation(FVector ReqMovement)
{
	MovementComp->AddInputVector(ReqMovement);
}

MovementComp is a simple UMovementComponent. If I call AddActorLocalOffset directly, I get the same result.

If I add another RPC from the server to the clients, then I get the expected results, but why do I have to? I thought the “Replicates” checkbox handled that automatically in the background. If not, why is that checkbox there to begin with? The client that’s in the same window as the server in PIE gets replicated correctly. The remote client on its own window is the only one not being replicated.

Movement component has it’s own replication that takes care of network lag and client side prediction. You don’t have to do RPC. Just call AddInputVector on client.

As far as I can see, replication only happens from server to cluent, so if I make a call to AddInputVector on the client, there will be no movement; Which is what I saw when I tried it. I believe CharacterMovementComponent does handle the message from client to server, but not the UMovementComponent which is what I’m using.

I know that would work (what I started with), but I do want to know why a movement that is clearly happening on the server is not being replicated to the remote client. Understanding how this system works is important to me but I’ve banged my head the wall on this one to no avail :\

One weird thing is that one pawn (the one for the listen server) gets a proper player controller, but the other one doesn’t. If I create a player controller for the other one, and attach it, it’s still broken. The server does try to create a player controller for the remote client, but something along the line fails (leaving no clues as to why), and never recovers.

My mistake. It refers to CharacterMovementComponent not PawnMovementComponent. My advice should work if you reparent to ACharacter and use AddMovementInput() method.

I still want to know why my pawn movement is not replicated to the client. Sure, I could fix this one specific case, but in the future if I move a pawn in the server, and don’t see the movement replicated to the client(s), I’d like to know why.

I was assuming I didn’t have to manually do the parameter replication stuff for position, but do I?

void ATestPawn::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const
{
    DOREPLIFETIME( RootComponent->RelativeLocation );
}

???

1 Like

If you take a look on engine sources, UMovementComponent class does not support replication. This means that even if you call SetIsReplicated(true) on server, nothing will be replicated.

If it goes to actor replciation, you have to call SetReplicates() and SetReplicateMovement(). Then it should be replicated with his location, rotation and all replicated properties.

If your actor has replication turned on, you change location and cannot see this change on clients - you probably change this location on client not on server.

btw. Relative location is component location in actor local space. Moreover You’ll have to override GetLifetimeReplicatedProps in your RootComponent, not actor that owns it.

Maybe it’s time to share this test project ?

Like I said, I tried it with ReplicateMovement and without it, with a movement component and without it and every combination thereof.

On the Pawn tick I have: if (Role == ROLE_Authority) which I think restricts it to the server. I also see the movement happen perfectly on the listen server, so I know it’s working. Just never propagated to the client.

I see nothing in Epic’s documentation about an Actor’s location and rotation propagated through the network if ‘Replicates’ and ‘ReplicateMovement’ are on.

Do I have to do GetLifetimeReplicatedProps for having the location propagated? Also not in the docs, but I haven’t tried it.

I’ll simplify the project to just this example and post it later.

I see nothing in Epic’s documentation about an Actor’s location and rotation propagated through the network if ‘Replicates’ and ‘ReplicateMovement’ are on.

link text

Do I have to do GetLifetimeReplicatedProps for having the location propagated? Also not in the docs, but I haven’t tried it.

GetLifetimeReplicatedProps can be used to replicate your custom class member variables. See:
link text
Location and Rotation that we’re interested in are replicated by ReplicatedMovement property filled in AActor::PreReplication function.

I guess that there are additional conditions that are blocking your example project from correct behavior. Project packed up will be helpful.

Bug in engine is a very brave hipothesis…
[][1]

AMyActor::AMyActor()
	:Super()
{
	PrimaryActorTick.bCanEverTick = true;
	TestTime = 1.0f;
	SetReplicateMovement(true);
	SetReplicates(true);
	bAlwaysRelevant = true;
}

[1]:

Ok I do see the line: “bReplicateMovement : Set to true if you want to be able to move the Actor and have its position be updated on clients automatically. Pawns have this on by default.”

Which is obviously not true according to my test case. I posted it as a bug as well, but I’ll look at posting a simple sample project to show it doesn’t work on the simplest case.

Brave, yet I think it was a bug in UE4 (though I appreciate the video and help).

So I commented everything out that wasn’t just the simple move-the-actor-in-the-server-tick. Ran it, and it worked. I thought, “great, now I can add everything back in one-by-one until it breaks and I’ll see what was wrong”.

I added everything one-by-one, testing after each addition. I ended up adding everything back in, and it still working. Same.Exact.Code. My conclusion is that it was a BS UE4 actor corruption crap like it’s happened to me so many times in the past. Such a buggy piece of crap codebase.

Sometimes removing Game/Intermediate directory helps. All glue code generated by UHT is stored there. after this you have to regenerate project files and reopen Visual Studio.

Hmmm… I know it’s been a while, but I had same problem, and the solution was actualy pretty easy. I forgot to call Super::GetLifetimeReplicatedProps( OutLifetimeProps ) on the beginning of GetLifetimeReplicatedProps func. I assume that you could have thesame, since you didn’t call it on your code example. I’m just saying if someone else did thesame mistake :wink: