Wednesday, October 28, 2015

game design - Authoritative Server Movement and Collision


I am attempting to write a proof of concept in preparation to do my first networked game. I have decided to do an authoritative server with client side prediction.


I am trying to implement my architecture like this diagram from an excellent article on the subject


Client Server Architecture example


In the article, the data that is synchronized is the player's position. This works great for turn based games, but what about real time games?



In my game, each entity has a position and a velocity vector. It is the server's job to detect collisions. I have attempted to send the server velocity changes, but I am having an issue where the server's position and the client's position begins to diverge because their clocks are not perfectly synchronized.


So my question is, is it standard practice to send positions as the synchronized state between a client and server instead of a velocity vector? Will changing to synchronizing positions instead of velocities open my game up to cheating? Is there a better way to synchronize the players' states with the server?


Also, if I use positions, doesn't that mean that the other players are going to be seen in a past state? Will that mean that the server might send a player killed message before the collision is visible to the player in the present?



Answer



Making good multiplayer games isn't a trivial thing, we know. There are many aspects to care about: network architecture, machines synchronization, network delays, cheating... But, let's start one step per time.


In turn-based games, as you said, you are limited to send objects positions, because that is the only important information you'll need. In real-time, fast-paced video games (such as FPS, racing games...), good timing is the key to make the game enjoyable, and mostly playable.


When playing an FPS there are many objects to sync: players, bullets, weapons, vehicles, and then scores, chat messages... The more the objects, the more the packets to send over the network, and with few to no delays independently of your connection. That means you need a proper network protocol to connect different players to play together. That means you can't rely on TCP, because you are focusing on real-time simulation and fast updates, not packets integrity and reliability. UDP is better for this task. Well, not UDP as is, but a custom net protocol built on top of it.


The image you posted shows a basic client-server interaction, where the server is authoritative over the client. That means the client always applies the information received from the server, whatever it is, because it is the server and it is always right. And it is right because it is the only one running the game logic, whilst clients are only replicating it on different machines. Also, clients should replicate exactly the server simulation: this is called deterministic lockstep. A system is said deterministic if we can know every single action to perform to get to a state B from a given starting state A.
A video game is a deterministic system: if I hold the 'move forward' key for a certain amount of time, I can foresee the position I'm going to be at (thanks, high school physics).
Deterministic lockstep - together with floating point determinism, the property of several machines to compute same results if given the same starting numbers and operations to perform - is the reason a client can simulate for a small amount of time what is happening on the server when some packets are suddendly lost, if given the right state information such as position and velocity instead of one only of them.

On the other hand, deterministic lockstep and client-server synchronization is only possible if both the client and server are running the same code, and assuming that there are no game logic delays because of internal application integrating/rendering time.


In the FPS scenario, a server must send clients many updates per second, so that they are always running the most recent simulation possible (for example 20 updates per seconds). This rate should be nor low enough to cause lag because of many server-side corrections, neither too high for the client machine to handle (we don't want to congestionate one's connection).


Syncing your game isn't just telling clients objects coordinates and velocities vectors, and updating; you must make sure clients are able to sync single entities as well as whole game session (e.g. when a player wants to join a game in progress). Or, your game should be able to compensate network latency so that shooting to a player is actually shooting to a player on the server: clients are running a simulation in the past because of networking, and there are efficient ways to prevent players from feeling frustrated for playing a "bad" game.


Now, answering your question: what info does one need to send to sync clients? The Quake source code shows how they dealt with client synchronization: the server receives from clients every players' input, and then sends every player avatar's position, speed and direction, this way - using the same physics code - both clients and server will compute the same frames after small amounts of time. Eventually the server will perform corrections over the clients, and there is some data to update instantly and other one should interpolate smoothly, but the game will maintain its logical integrity most of the time. And let's not forget client-side prediction!


You can read more about networked physics, server authority, client-side prediction and server-side compensation here. Also, the Valve Developer Community is a place full of interesting guides to understand better how their engine (and, generally speaking, any possible engine) works.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...