Sign in to follow this  
Dark Dude

Client-Server Synchronizing In An FPS

Recommended Posts

Dark Dude    122
I've been reading round many papers and threads and whatnot and they all seem to say different things, so... how exactly is it done for FPSes in OpenGL? I'm expecting to use UDP in a client-server architecture, wherein the server is the master of all the clients, but I'm not sure how to go about the actual synchronicity. Should I be sending states or actions? How often should I be sending these? How do I deal with latency? Anything else I need to know? The FAQ is nice, but doesn't seem to provide much on this particular area, so much help would be appreciated. I prefer to plan and design than jump into code, so... yeah p_o

Share this post


Link to post
Share on other sites
Kylotan    10008
Quote:
Original post by Dark Dude
I've been reading round many papers and threads and whatnot and they all seem to say different things, so... how exactly is it done for FPSes in OpenGL?

Just so you know, OpenGL is for just graphics, and has nothing to do with the networking nor affects it in any way.

Quote:
I'm expecting to use UDP in a client-server architecture, wherein the server is the master of all the clients, but I'm not sure how to go about the actual synchronicity. Should I be sending states or actions? How often should I be sending these?

I believe most people are sending a mixture of both states and actions, but bear in mind that you may need to consider implementing reliable transport for actions to ensure that important messages aren't lost. For example if you clicked to fire a rocket at a prone target you wouldn't be happy if the packet with the 'fire_weapon' action (or whatever) didn't arrive at the server and nothing happened.

The speed at which you need to broadcast state out from the server to interested clients depends on how frequently important events can happen, because the longer you wait between transmissions, the more of a difference there will be on the client and server. I'd suggest starting with 5 to 10 updates per person per second, where the update includes your opponent's positions and directions, and see how well that serves you.

Quote:
How do I deal with latency?

Different games have different approaches to this, with different pros and cons. The Valve networking model for example attempts to compensate for latency client-side, so that your actions are resolved as if the client's state is completely consistent, even though on the server things may have changed. This makes the game play well from a shooter's point of view but is technically inconsistent on the server. Other games do it the other way around where you have to manually compensate for your own latency when aiming but there is never any doubt over the consistency of the result.

On a very basic level movement latency is covered up somewhat by having a system that can smoothly interpolate between a client's predicted position for an entity (based on previous position and movement data) and the server's reported position for an entity. The first is up-to-date but potentially wrong, the second is definitely right but out-of-date, so blending between these two gives you a good compromise between responsiveness and accuracy. And the more often you send your state updates, the smaller the difference between the two will be.

That's the general overview. Perhaps some of the other posters who work more in the FPS area than I do can post some code examples or formulae for you.

Share this post


Link to post
Share on other sites
tomva    172

Hello Dark Dude-

I've also been writing my own networking library for an FPS and had many of the same questions! Kylotan said it correctly: every game does it a bit differently. There is no right way, but depending on your use case one way may make more sense than another.

In my case, I opted for UDP only. There are some practical reasons for that (such as code simplicity) in my case, but the real reason was that I had a networking model in mind and I wanted to try it. My model is this:
- client and server exchange all state via UDP packets
- the client has to expect the server will lose some of its packets and vice-versa
- when the client sees something it doesn't understand (new object just appeared, etc.)
it can query the server for information about it.

I like my approach because it is simple and there is just one code path that runs, and it works in the happy case (low latency and no network data loss) and the unhappy case (high latencies and/or network data loss).

But talking to others on this forum, many real games don't do that. They'll often just set up dedicated TCP connections and let the low level networking layers handle all resends etc. That is also simple, although then you need separate code to handle what happens when the connection resets etc.

In my case, for instance, I do have to be careful about sending commands to the server. If the user clicks the "fire rockets now" button and the packet is lost, the client will be unhappy. There are multiple strategies for this (including simple ones such as sending the request multiple times), but it is something to think about. Obviously that's not a problem in the long-lived guaranteed TCP connection.

Regardless of how you do it (UDP vs. TCP, etc.), there are several common elements:

  • Should I send states or actions? I recommend sending state wherever possible,
    and actions only when that's the only way to do it. For instance, if a new
    object enters the map, the server will just start sending that state to the
    client, and the client figures out that the new object was added. I like that
    better than a bunch of "new object added/removed" events. But that's more of
    a personal preference than a real rule.

  • How often should I be sending these? I'd love to hear what most games do. I've
    heard updates on the order of 10-50 Hz is reasonable, although it all depends
    on the game. You can do some back-of-the envelope calculations to figure out
    how much state you'll want to send.

  • How do I deal with latency? You're going to have to compensate for it on the
    client. The Valve documentation that Kylotan mentions is really worth reading.
    The client knows it is behind the server, so it will have to guess where objects
    "really" are, and update its predictions as it gets updated state from the
    server.

  • Anything else I need to know? Think hard about network splits. What if the client
    is blocked from sending data for 2 packets? For 20? For 200? What if a bad
    router repeats a bunch of packets, will you be okay? Think hard about cheating.
    Do you care? If so, make sure a cheater can't spoof packets, or read other peoples'.
    Look into encryption and compression. Consider that there will probably be a lot
    of state on the server and you can only send a small fraction with each update.
    How will you make sure the client eventually gets all the state updates? Look at
    prioritized network request queues for that.


Also, you may want to look at pre-existing libraries :) I've heard of RakNet, for instance, but I haven't used it.

I've really enjoyed building my own networking layer because I wanted to learn. But it has been a lot of work and I'm still not done yet.

-Thomas

PS: the Valve documentation: Valve docs.

PPS: here is a link to some of my own documentation, with additional links: AESOP networking.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this