Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Currently in my game, the client is nothing but a renderer. When input state is changed, the client sends a packet to the server and moves the player as if it were processing the input, but the server has the final say on the position.

This generally works really well, except for one big problem: falling off edges. Basically, if a player is walking towards an edge, say a cliff, and stops right before going off the edge, sometimes a second later, he'll be teleported off of the edge. This is because the "I stopped pressing W" packet is sent after the server processes the information.

Here's a lag diagram to help you understand what I mean: http://i.imgur.com/Prr8K.png

I could just send a "W Pressed" packet each frame for the server to process, but that would seem to be a bandwidth-costly solution.

Any help is appreciated!

share|improve this question
add comment

2 Answers

While the server has the final say on the position, it should do that by verifying and sanity-checking what the client sends over as the inputs and position. I say this because what you're doing is moving the player immediately and the expectation that creates in your code is that the client is the real position.

You think it generally works well, but it's not. Side note: you say that your client is nothing more than a renderer, then promptly give it local control to move around without server messages. You can't have it both ways, either wait for the server to tell you to move or assume some control over your position and use the server to verify cheats.

I note that your responses are reaching one whole second? That's 500ms latency which is ridiculously large for any kind of action game. Try to find out why this turnaround is taking so long, it could be anything from command queues backing up from not getting handled promptly to flooded bandwidth or even demons causing many lost packets.

What I think should happen is that

client sends a move + position update
server gets it t+latency time later
server verifies and sends out info to all clients
client receives this at (t+latency + latency)

The tricky part here is that if a client receives a message about itself it should mostly ignore it unless that message is something like "invalid move, go to XYZ instead." If that message is for anyone else's client that you're getting info about then you'll have to extrapolate forwards in time so it looks to be kind of where it will be.

share|improve this answer
    
The client doesn't send its position at all; it simply predicts/interpolates. That's why it falls off edges when it thinks it's on the edge. Also, I don't see where I said the lag was 1 second, it's more like 8ms (local testing) to 100ms (over the internet). I said the player was getting set back later because I periodically send out full position updates. Am I correct in understanding that I should send the position that the client thinks it should be, along with the keys that were pressed, and the server should verify f it's possible? –  Thomas Oct 1 '12 at 2:13
    
"sometimes a second later, he'll be teleported" impliedthe big delays, which is where I got the time from. For a responsive action game yes, the client plays and the server plays behind in time and lets the client know if it's done something illegal. You'll notice in online multiplayer games you mostly see other people shift positions (those come from the server) while your own position only very rarely changes from direct server corrections. Other people see you shift position, etc... –  Patrick Hughes Oct 1 '12 at 5:30
    
Couldn't this still cause the player to fall off the edge on the server though? Unless I send a packet each frame, the server could still think that the player is moving for about 32ms. (I only send packets every three frames). Or are you suggesting that I don't simulate input on the server at all, but rather only check if the position is in bounds of the input pressed? –  Thomas Oct 1 '12 at 6:56
    
Since the server only corrects invalid movement reported by the client, it would never send out a "you fell off the cliff" unless the client itself drove right over the edge. In this feedback loop it's the server that corrects itself to the client's view of the world and his place in it. Movement will feel crisp and responsive to the player. Other actions like interacting with world objects will involve waiting for the server to tell the client what just happened, click a box and wait for response, but we're just talking about movement here. –  Patrick Hughes Oct 1 '12 at 15:24
    
That sounds a lot like what I'm currently doing; sending a position to the server and having the server validate whether the player could have moved to that position. That seems to be a more heuristic approach though, and in my opinion wouldn't be nearly effective as having the server decide, period. Would sending timestamps with each packet work? I think that would eradicate the issue. I believe that Halo and games that use the Source engine use that. –  Thomas Oct 1 '12 at 22:55
add comment

I understand you question as:

The server gets a packet when I start pressing the 'forward' button and another packet when I finally released the 'forward' button. Therefore the actual movement on the server starts and ends about 100 milliseconds 'too late' in actual game vs. what the player is expressing on the client-side. So if the player wants to move 10 seconds, he may end up move 10.x seconds instead where x >= 1 online.

This is a bad design strategy because it does not express the player's will in the game world as the player intends, creating a rather poor user experience.

The solution I would recommend is sending a packet (as often as you can) that indicates how many steps the player took and in which direction. The server then updates the game world with the new player location if it passes a correctness check. So the player can move with great precision and avoid falling off high ledges.

The alternative would be to remember the player's positions in the past second and correct the position in retrospect to the time the button was released. Sounds like it would create that rubber-band effect of the olden days.(only for a different reason)

So basically you would need to send a packet of which button is pressed and what was the actual game time the button was pressed and then later, which button was released and at what exact time.

share|improve this answer
    
As I said to Patrick, I think that solution would be more of a heuristic approach; instead of the server being "The Man", the server instead checks client data for validity. This of course, will have to create some leeway so that lag or other network issues do not create false positives. –  Thomas Oct 1 '12 at 23:25
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.