I have been implementing my own networking for a third person multiplayer game, but controls and physics will be ala old school FPSs. I'm using Unity's transport layer, which allows me to send and recieve raw data between server and client.
I used this model as reference, in order to implement better client response: http://www.gabrielgambetta.com/client-server-game-architecture.html
Implementing prediction, and interpolation was no problem, but I'm having a problem implementing reconciliation, even though I successfully implemented for normal ground movement.
I do the following each tick:
- Client: The client sends the server the delta updates on the player position, and the server validates this movement and updates the player accordingly on the server.
- Server: I send a snapshot to all clients with all players' positions. Each client interpolates the rest of the players, and reconciliates it's own position.
Ground movement seems easy, because each frame the player input determines how the player moves: Each FixedUpdate, the player moves a certain distance. This makes reconciliation really easy, since knowing which was the last input the server has received, your client just needs to consider the rest of the inputs yet to be processed.
But I don't know how to deal with jumping. Jumping is an input that has an impact on the player's position over several frames: while it's airborne (and for a few frames, as the placer decelerates in case his air speed was high).
This means I can't just rely on the input "jump" to recalculate my client's position, since depending on the moment I'm present, I could be ascending, or descending. Even more, if I jump and collide with the roof, killing all my vertical speed, the movement would be completelly different.
This lead me to think I should be sending to the server each update on the player's position: Instead of sending "hey, im jumping here", I could send "I'm moving up 1 unit"..."I'm moving up 0.9 units".... describing the players parabole. But I feel this method is not enterily secure, since the client could be sending "I'm moving up 1" ever single time, allowing the player to just fly away. So the server has to be the one handling the physics on the jump.
This problem is also present in anything physics related: When the player is pushed away by an external force set up by the server or the client itself. If the client recieves a message saying has been affected by an explosion, I could set the client's speed accordingly, but: - If I have any kind of air control (which I want to have), I need to tell the server the change on air speed - If the server makes a correction on the physics made, I need to be able to predict and reconciliate the position AND speed. For example: If I collide against a wall in the server, which for some reason, is not present in the client, I also need to kill the player speed or it will keep slamming into an invisible wall.
There are several solutions I was thinking about, but I'm not really satisfied with any of them:
- As said earlier, I could could let the client handle the air movement by sending the position update back to the server, but this feels insecure since th client could technically make himself fly around, and make himself immune to being pushed away.
- Besides sending the player positions, I could also send the players' speed, storing this information could make reconciliation easier and more reliable, but it will also increase the size of snapshots and network usage.
Maybe I'm missing a clever alternative, but I don't really see any other option. Any ideas?