RPC: Client not seeing the result of its own function calls

Hi,

My problem is pretty straightforward, but I can’t seem to find anyone else having that issue.

I am running a dedicated server and testing my game with three clients in the editor.

The functions in my player controller are tagged with “UFUNCTION(Server, Reliable, WithValidation)” and have indeed an “_Implementation” and “_Validate” present in both the .h and .cpp.

The issue that I have is that when calling such a function, the server executes it successfully, and the other clients properly see the actor change due to that… However, the client that called the function will not see anything happen.

What am I doing wrong?

Edit: Some logs with two clients on a dedicated server, and one pawn moving forward.

    LogTemp:Warning: --- MainGameMode: Tick ---
    LogTemp:Warning: Pawn AUTHORITY Location : X=1002092.875 Y=549.376 Z=1478.468
    LogTemp:Warning: Pawn AUTHORITY Location : X=1000000.000 Y=0.000 Z=1000.000
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1000000.000 Y=0.000 Z=1000.010
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1001000.000 Y=0.000 Z=1000.000
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1002093.000 Y=549.000 Z=1478.010
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1000000.000 Y=0.000 Z=1000.000
    LogTemp:Warning: --- MainGameMode: Tick ---
    LogTemp:Warning: Pawn AUTHORITY Location : X=1002101.188 Y=554.257 Z=1481.747
    LogTemp:Warning: Pawn AUTHORITY Location : X=1000000.000 Y=0.000 Z=1000.000
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1000000.000 Y=0.000 Z=1000.010
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1001000.000 Y=0.000 Z=1000.000
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1002109.000 Y=559.000 Z=1485.010
    LogTemp:Warning: Pawn NOT AUTHORITY Location : X=1000000.000 Y=0.000 Z=1000.000
    LogTemp:Warning: --- MainGameMode: Tick ---

The pawn at X=1001000 shouldn’t be here, but at 1002XXX.

Can you show us what you are doing inside the _Implementation function?

Of course. Here is the “MoveForward_Implementation” for instance. All my replicated functions follow the exact same logic, with the only line changing between them being, obviously, the “controlledPawn->doSomething()” one.

void AMainPlayerController::MoveForward_Implementation(float AxisValue) {
    auto controlledPawn = Cast<AShipPawn>(this->GetPawn());
    if (controlledPawn)
    {
    	controlledPawn->MoveForward(AxisValue);
    }
}

The “MoveForward” of the pawn itself doesn’t have replication rules, if that information can be of any use.

I don’t see any issues with this code.

The only thing I noticed is this is a Pawn, not a Character. I have only used Characters because only Characters contain Epic’s predictive movement system (CharacterMovementComponent) and without that things don’t seem to work very well. I really wish there was a more generic PawnMovementComponent, but if you look at the source code for CharacterMovementComponent you can see why they can’t easily convert it to a more generic system.

Hmm that’s very interesting! It must be the only major difference between my project and most of the tutorials out there, as I am indeed using regular pawns and not characters.

Unfortunately, I don’t think that I will be able to convert my pawns to characters, as I need six degrees of freedom. But I’ll definitely look into the code :slight_smile:

Yep, I understand why a Character won’t work for you. Characters are meant for bipeds only.

I believe you can still get replicated movement to work for Pawns fairly easily. Sounds like you are close and there is probably just a minor bug in your code based on using Tutorials meant for Characters probably. But I think what you will find is that when you fix the minor issue and get the movement replicated, lag is going to cause your Pawns to jitter and jump all over the place :frowning:

As I was searching for info on replicated Pawn movement I found a tutorial meant for Pawns. Maybe this has something that will help:

The movement is actually quite smooth. I’m sure that if you zoomed in a lot, you’d see some jitter, but so far in a local host configuration, it works relatively well.

(As I said, the client does manage to send its calls through to the server, so when I press the keys I already see it moving and stuff… On every screen except its own)

Of course with a high ping, nothing is guaranteed, but there’s only so much prediction could do anyway.

Very interesting! I’ll definitely take a look :slight_smile: It even covers 6dof. Maybe seeing the blueprint logic will give me some hints.

Yeah, not moving on just its own client is a strange one. Haven’t hear that one before. Usually it is the reverse :slight_smile:

The predictive movement is actually really amazing. Try using the following console commands (~ to bring up the console in editor) to simulate lag. I have seen a lot of people’s blueprint games completely fail when simulating lag, so it is good to give it a try every time you change how your replication works:

Net PktLag=500
Net PktLagVariance=100
Net PktLoss=15

I just saw a similar question here: Client Pawn replication not working client side but works server side - Programming & Scripting - Unreal Engine Forums

The short of it is that this person marked their question as “answered” when they opted to have the client execute a function locally, then have the server execute virtually the same code remotely.

That’s definitely a solution, but it seems quite surprising that executing a function on the server would get “ignored” by the client that requested the execution…

Very interesting command, thanks a lot!

It sure does break my game :stuck_out_tongue: When I run it, after a few seconds of commands reaching the server more slowly than usual, the client that lags out just gets kicked out of the server and becomes independant (and can see itself move now that it has become its own server)

Because the method itself is just an RPC that is called on the server, so the client has actually no work there. A common pattern is to make the server call and the client call directly to simulate the action instantaniously. That way the server may correct the action but the poping will be minimal (plus any lag compensation code etc would help too).

That makes a lot of sense, but in both our situations, the issue is that the server never corrects any action, whether you call a client-side copy of the function in the meantime or not.

This person: Multiplayer Pawn movement synchronization problem - C++ Programming - Unreal Engine Forums is also having the same issue. They had to replicate the movement data and change the pawn role temporarily.

Something is clearly really wrong here.

Ok, I built a test project using Pawns and DefaultPawns myself to try this out. I was horrified to find that Pawns do not support multiplayer games at all. Very sad. But I guess Pawns are meant to be a placeholder to build your own system and add your own network code.

If you are just trying to get your pawns to move, the following worked for me:

The results were horrible with any kind of simulated lag. So this isn’t really a solution for network games, but if you just want to see your pawns move on all connected players, at least that happens.

It seems what we really need are more variations of CharacterMovementComponent that support more replicated movement modes than just bipeds. I have created my own variations of CharacterMovmentComponent to add my own movement modes, but I have never written a CharacterMovementComponent from scratch. If you take a look at the source code you can see that it would be a fairly large project.

Thanks for taking the time to test this out! I’m very glad that a veteran like you could confirm that I haven’t missed some obvious solution for what I’m trying to do. You have also provided me with very helpful suggestions and potential solutions :slight_smile:

I’ve gone for this solution at the moment: Multiplayer Pawn movement synchronization problem - C++ Programming - Unreal Engine Forums

By also calling a duplicate of the function client-side right as you do the RPC, the position adjustment from the server data is minimal.

Sure, it still performs horribly with any kind of lag, but at least that’s a start. I wanted to get the multiplayer working, at least on some level, for my project, so that I know how I need to code the rest of the game to be multiplayer compatible.

If there are issues of smoothing and lag compensation, they can be sorted out later during the polish phase. Worst case scenario, I have to code my own lag compensation using what is available in the CharacterMovementComponent… That’s not too bad considering the code is relatively well commented and explained.

Before I leave this part of the project (setting up basic multiplayer replication) and move on to the next, I will try to see if adapting a Character for 6DOF would be at all fesible, and would provide a better result.