Howdy!
Welcome back to my blog series on writing a networked player controller in Unreal! Last week we wrapped up the latency mitigation techniques for the local player so that all player input and movement is simulated locally and then synced with the server on every network update.
This week, we will start the same process for the other players in the game with Entity Extrapolation!
Our new friend
The problem
You might be wondering, why are we doing any of this anyways? If we're doing client-side prediction for every player in the game, then aren't we already replicating all of our movement? Well, yes, we are nearly perfectly replicating each player's own movement to themselves but we are not yet replicating the movement of the other players in the game.
The diagram above illustrates the problem I'm referring to. Other clients only receive updates on the player's updated position each time they receive a network update (in this case 100ms) which results is choppy movement, not ideal for smooth gameplay.
If we simply update the other client's position when we receive a network update from the server, as shown in the code above, we will see the same result in our simulation:
Average Conditions:
Bad Conditions:
Entity Extrapolation
As shown above, we need to employ some sort of strategy to mitigate the inherent latency in replicating player movement to other clients. The first strategy that we're going to use is entity extrapolation.
As a refresher, entity extrapolation is the idea that the server will not only send updated positions of the players in the game but will also send information describing the velocity of the other players. This is so that each player can then use that velocity information to attempt to extrapolate where other networked entities will be moving before the next server update.
In our implementation, I achieved this by totaling each player's movement over the last server update and then dividing it by the server update rate (100 ms is the update rate I chose). This velocity is then sent to each client with a NetMulticast function.
When this multicast is received by an actor with the role ROLE_SimulatedProxy (meaning that owning player for this actor is another player, not local to this client) then sync the client's position with the update from the server and set the player's simulated speeds and direction.
Then on each tick for these simulated proxies, we apply that movement speed scaled by time so that we move the player at a constant speed:
Average Conditions:
Bad Conditions:
What's next
As you can see, entity extrapolation doesn't really work well for player controllers, or any networked entity that can change speed and direction instantaneously. It really only works for slow-moving, slow-turning entities that have predictable motion. This is why next week we will be implementing Entity Interpolation which provides a much better simulation for other player controllers. Github:
Comments