0
\$\begingroup\$

I am developing a small multiplayer game with XNA. It's a usual client-server architecture -- I have a server and many clients communicating with it through UDP (via .NET's Socket class). These clients send data to the server (for example, the player's position) and the server handles it and decides what to do (send it to every other client or drop it).

What's the most efficient "correct" way to send position of moving object from a client to a server? Currently, I send the client's ID and player position 60 times a second (XNA's default update rate) while a player is moving. When I see my own player on the screen, it moves very smoothly, but other don't, despite every client having the same update rate. What am I doing wrong?

\$\endgroup\$
4
  • 6
    \$\begingroup\$ do you log how many packets actually reach their destination? UDP isn't a reliable protocol. Packets can get lost or reach the destination in the wrong order. \$\endgroup\$
    – Philipp
    Commented Aug 10, 2013 at 19:11
  • \$\begingroup\$ I think this is too broad to answer. Could you localise the issue? It could be caused by network latency or jitter or even be a rendering issue. We're left guessing. \$\endgroup\$
    – Anko
    Commented Aug 10, 2013 at 21:01
  • \$\begingroup\$ When you are using UDP like this you might have to force a checksum to make sure everything gets transferred correctly hence the server can take an appropriate action. \$\endgroup\$
    – OmniOwl
    Commented Aug 10, 2013 at 21:07
  • \$\begingroup\$ Are you sure you're getting the update packets at 60 Hz? There can be any number of reasons why you're sending them at 60 Hz but getting them late or batched or whatever. I'd start by verifying that. \$\endgroup\$
    – ggambetta
    Commented Aug 11, 2013 at 9:39

3 Answers 3

3
\$\begingroup\$

Those packets are still late. Even if you send 1M packets every second, there is still lag. Certain packet is packed at time t1 and it arrives at t1+ping/2.

You send positions of other player to everyone. I assume you then do something like this:

player[4].Position = new Vector2(readNextPlayerX(),ReadNextPlayerY());

You set that coordinate you sent, directly to player with matching id?

When you get new coordinate, you just apply it and if it has changed a lot, you get jerky movement. Difference between last known position and just updated position is so big, that it just leaps to it. To fix this, you have to use "lerp" to smoothly move towards new coordinates. This is called Interpolation. Instead of immediately move to new position, you have to keep record of you new positions, sent from server. Then in every update loop, push player towards next position. Lerp is a way to move towards other point, certain amount. This "amount" is called "smoothingFactor". It can be number between 0f and 1f. 1f means that vector1 changes to vector2 in:

MathHelper.Lerp(vector1,vector2,smoothingFactor);

if it's 0.5f, vector1 moves towards vector2 to halfway. So if distance was 10, its now 5. Depending on your smoothingFactor, you can change your movement from jerky, to smooth.

You are sending 60 times per second. That's way too much. If you have 10 players and you send 60*2 floats and int to server, that means server sends 9*60*2 floats and 9*int to everyone, every second. 20 or 30 times is better. You collect data on server, for player inputs. Generate movement packets from that data. Every 30ms you send collected data to players.

Are you using your own networking code, or some library? Packet dropping can cause this also.

\$\endgroup\$
1
\$\begingroup\$

I'm no expert on this , but from what I can remember the best way to do this is to just send packets when actions are taken and not the whole time.

Example:

Player presses a button to move > send to server > send to other players > display stuff on clients Player releases button > server > other clients ...

That way you don't have to send so much data. Granted it might be the reason for some problems, like, misleading actions when a packet isn't received/sent , but from what I have heard his is the best way to do mp gaming. (just not sure if UDP is the best protocol for this as mentioned by others)

\$\endgroup\$
0
0
\$\begingroup\$

It looks like you have a pretty good idea of what to do, but there are a few things you really need to look at. I'll briefly talk about them but you really should look over some of the concepts applied to the source engine here. Additionally, there is a good post here which talks about syncing physics over networks and some more details.

I have no real idea 'how' you implemented it, but the concepts below and in the articles are likely going to apply:

Real-time game with low entity count is usually handled with UDP and sending frequent packets (10-30 times a second, depending on how much data you have and how good of a connection you are running). If you are targeting mobile phones keep your data packets small and only send them 10-20 times a second. So using UDP is a perfectly fine, just realize you MUST interpolate because you will have dropped packets (unless you are on a LAN with minimal networking activity).

In all cases for a client-server, your clients shouldn't be determining the positioning information because this means your server cannot easily determine people cheating or not. Usually, the server does the physics then your clients are updated. (P2P follows a very different style so I won't talk about it here). You don't need to update more than a few times a second because you will be interpolating between network updates to keep your client running smoothly at whatever framerate they are.

You likely are going to want to do lag compensation of some sort. (I.e. the famous "user is slowing down the game" you see in Starcraft 2). Your client can run physics to allow you to do client-side prediction, but that has a debatable cost/benefit and is usually worse the more physics objects you have colliding in your game.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged .