Recommended Posts

hi, I was just wondering... would udp be stable enough to send object state changes across a fps online game.
for e.g. when one player opens a door an OPEN_DOOR msg could be sent in a udp packet to every other client but I've read that udp is unreliable and that packets could be lost so what if one client doesn't recieve the OPEN_DOOR msg and gets stuck outside (or inside) ?? and has to witness other players walking through a closed door?
would I need to broadcast every object's state constantly every so often if I'm using udp?
what about games like quake? they must need to send some pakcets of data at the beginning of the game to let players know about each other (names, character skins etc.) what if these get lost?

0

Share this post

Link to post

Share on other sites

Look at question 12 of the Forum FAQ for how quake and others do things. About using UDP you can send reliable UDP packets by implementing parts of TCP yourself. Question 11 covers libraries. ENet and others have support for reliable UDP. Also are you positive you want to use P2P? Question 30 is new apparently and covers some things.

Share this post

Link to post

Share on other sites

Original post by staticVoid2I've read the links you posted and about quake... they basically send all object states every frame and use delta compression?

You delta compress in-memory, using the difference for each entity state between the ack state and the latest state, and you can compress that packet further with Huffman compression. Entities that haven't changed since the client ack number don't need to be sent. That means that the first state sent to a client (snapshot), will be much bigger than updates, since you need to send the base state of every entity in the game.

But since the sending is done during map loading, or can be throttled easily for clients joining games in progress, that's not a problem. Loading can take quite a while depending on the size of the initial game state.

Quote:

what happens if they run out of room to store everything in one packet, or is this a limitation they impose.

No limitation is necessary. You can design a packet segmentation and reconstruction manually, it's not that hard. But you can use the UDP limit (64K) if you think your packets will never reach that limit.

Quote:

I think I'm getting mixed up about the server client model... would the server calculate everything such as the current frames in animation etc. and then send this to each client?

pretty much. Although the more dead-reckoning you can do on clients the better (basically, make educated guesses to save bandwidth.

Quote:

and what does the client send to the server, just the key/mouse input or more?

Share this post

Link to post

Share on other sites

Original post by staticVoid2thanks for all your help, I have one more question (if you don't mind)...

for data that remians fairly constant such as player names etc. would this data also need to be sent every frame?

Nope. The static data would be part of the initial base state. However, since the data doesn't change, as soon as the client aknowledge the base state, that data does not need to be sent again (the delta compression will detect no change and will not send it).

This can work better if you 'lock' your update until the first state is aknowledged. If you can send the initial state reliably and wait until the client aknowledges it before sending further updates, you can 'throttle' the bandwidth and make sure you are not sending data more rapidly than your connection can handle (something TCP/IP does automatically, but you can roughly emulate that protocol through UDP).

But that's if you have a lot of static data with a large initial state. Say your initial state is 24K kilobytes in size, and if you limit your outstream bandwidth to an 4KBytes per client (16 clients -> 64kBytes outstream -> 512 Kbits outstream, what a pretty good DSL line could achieve), it could take up to 6 seconds to send that initial state to every clients. So it's not something to be sniffed at :)

Sending the initial state reliably can be as simple as sending each segment (say your UDP packets are 1200 bytes in size, and your state is 24K total, that will make about 20 segments) one after the other and repeat, until the client aknowledges that he received everything. Packet loss may mean some of the segments might get lost in the process, so you'll need to resend them.

It's not optimum, so it could take quite a while if you have lots of packet lost.

Share this post

Link to post

Share on other sites

The first solution is more authoritative, and that's what I would do. Then it will also save bandwidth, since you wont have to send the flag position every frame (as the flag will be moving around when carried).

Also, with interpolation and client-side prediction, the positions of the player carrying the flag and the flag itself may not be 100% in sync, so you'll end up with a 'floating' flag near the player, but not exactly where it should be. In L4D2, you can sometimes see that effect when a charger or hunter pins down a player.

You will probably need to send the position of the flag when in the dropped state. But as soon as it is carried, that position doesn't need to be updated. And when it's dropped, the position would be welded set on the floor, and not change (unless you want the flag to bounce around, but that can lead to exploits and bugs where the flag ends up in unreachable places).

Triggering events based on states can be a bit of a problem. You can either trigger events client-side by detecting state changes.

- player A picks up the flag. flag state changes from ON_FLOOR to CARRIED -> display "player A picked up the flag".

- player B steals the flag from player A. - player carrying flag changes from A to B. -> display "player B stole flag from Player A".

but you can miss events if they occur in rapid succession or if you experience packet loss.

I suspect that's what happens sometimes in Quake3 when some events dont get registered on clients (commentator misses to inform a client that something happens).

However, as Carmack said, the state-based approach of the Quake3 network engine virtually eliminates the need to send reliable messages and commands, as the client can work out what to do when the state of an object changes.

For example, when the server starts loading, you can either send a "start loading map(x)" rpc call to the clients, or have a "loading state" object that changes from "lobby" to "loading map(x)". Then the clients know what to do by comapring the previous "loading state" they receive to the new one.

Share this post

Link to post

Share on other sites

To solve the "who picked up the flag" problem, you let the server arbitrate.

1) Player locally detects picking up the flag.2) The flag is removed from display on the local client, and a message to request the flag is sent to the server.3) The server checks whether the flag is available where the player is.4) If the player could pick up the flag on the server, the server sends the "player A picked up the flag" message to everybody5) When the pick-up message is received, everybody display player A as carrying the flag.

This will work even if player A misses the flag by a fraction, and player B picks it up. What will happen is that the flag will locally removed (because A picks it up), and A will send the message to the server. B will actually have picked it up, so the message received from the server will be "B picked up the flag," which in turn means that A knows to display B carrying the flag, not A.