Sign in to follow this  

Best way of moving an online character

This topic is 2652 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, still working on my multiplayer game. I've got a rudimentary IOCP server connecting to the client and now I'm thinking about the best way to code the interaction for transmitting the player's position from client to server and back. I was hoping those who had gone through this before might offer some insight.

Here's the approaches I have so far. Note that each of those would also include client-side position interpolation and extrapolation to handle network lag conditions ... I'm only worried about the actual encoding of the position updates between client and server now.

(1) The "Virtual Keyboard". Whenever player presses a move button, I send the "key down" command for that key. When they release it, I send the "key up". Same thing for mouse-based movement. Server takes those keystrokes, converts them into move commands, updates position and transmits back to client.

Advantages: easy to understand and code.
Disadvantages: Very low-level. If a packet gets lost, a player might run forever.

(2) The Timed Command Stream. Every 100ms or so, the client sends the server the latest move command. Server uses commands to update client position, transmits new position back to client.

Advantages. More redundant. Higher-level, allows more abstraction between client and server.
Disadvantages. More complex. Higher bandwidth (e.g.moving forward takes a continual stream of packets).

(3) The "Nanny" Approach. Client is responsible for maintaining own position at all times. Transmits actual position (not a move command) to the server every 100ms or so. Server validates position constantly (using same physics as client) to prevent cheating, but only sends back position updates if a move is found to be invalid.

Advantages: Least bandwidth of all approaches.
Disadvantages. Server validation is much more complex, as it can't just calculate a new position, it has to ensure there is some valid path between old and new position, as well as ensuring max velocity wasn't exceeded, etc. There could also be some strange synch/timing issues in some cases, for instance if the client transmits a new position after the server has teleported the player or changed world geometry (for example, if a door closes in the player's path) but before the client has gotten that update.

(4) Some other approach I haven't though of.

Any feedback on whats typically done in these cases would be much appreciated. Thanks.

Share this post


Link to post
Share on other sites
I would go with (1) at a slightly higher level. Instead of sending down key states, send down action directives, i.e. instead of "key down", send "move forward", or "fire weapon", or "jump". The sever doesn't care about how the client came about a request, whether it be through a key press or a mouse button or a timer or a recorded replay stream, it just wants to know what the client is trying to do at the gameplay level. Issues like packet loss aren't a concern of this system since it's handled by your networking layer, which can use reliable transmission.

Share this post


Link to post
Share on other sites
AFAIK, (3) is what normally happens, and validation is not done as strictly as you might imagine, simply because it usually doesn't matter that much if the user is allowed to noclip around a little. If it ever does, tighten up validation in that area, or redesign your gameplay.

Sync is not a major problem, since movement-post-teleport type updates will be rejected automatically (since the client would effectively be requesting a re-teleport that far exceeds the maximum velocity). Getting to squeeze through a door when you shouldn't be able to (or vice versa) shouldn't usually be a big problem either. If there's some kind of scripted "the door always closes right in front of the player so the NPC can deliver a speech" type thing, then enforce it, on both sides.

Remember, client hacking could theoretically go so far as to ignore everything the server ever says. But at that point the player has a single-player game and a chat line - gg.

Share this post


Link to post
Share on other sites
Thanks for the replies. #3 is what I was leaning towards, I just wanted to make sure there weren't any hidden gotchas I was missing.

Antheus, its more of a generic MMO engine at this stage; primarily as a testbed for me to test the feasibility of some AI ideas I have.

Share this post


Link to post
Share on other sites
Here is how i do it in my 2D networked game, similar to a combination of option (1) and option (2);

1) The client sends a request to the server to move to final position x,y.
2) The server validates this final location (e.g. is it a position the player may stand on, is anything blocking its path) and calculates the A* route to this position from the player's current position.
3) The server then sends movement updates to the client periodically if the move is valid, that make up the route from their original position to the final position, the client extrapolates the route so it does not need a complicated pathfinding algorithm, for the most part bresenham line drawing suffices, with a few tweaks. If the player has higher agility, the movement updates are sent more frequently. On average, one will be sent every 0.5 seconds. Because the client extrapolates the position between the movment points, a single lost packet or a small amount of lag does not affect the game too much.
4) If the client changes their route while still on the move, the client sends a command to the server as normal, but the server sends a special command which informs the client it should first flush its 'queue' of pending movements, and then accept any new input from the server as verbatim. This gives the client better response times if they are clicking all over the map, e.g. in the middle of combat.

Let me know if this helps at all for your own solution! :-)

Share this post


Link to post
Share on other sites
Thanks Brain. I'm not sure if your solution will work in my case, however, because as a 3D-oriented engine, the client is picking only a move orientation, rather than a final destination.

One question that leaps to mind, however. In your version, if a client changes their destination, wouldn't you want to immediately flush the move buffer -- and set a flag to inhibit further move buffer updates -- until the server has acknowledged the change? Why wait for the server to acknowledge, then flush?

Share this post


Link to post
Share on other sites
i suppose either way works, currently all commands wait for server confirmation as the server is authoritative, so if the client makes a change that the server has not authorised it could end up out of sync with the rest of the clients.

Doing this your way would probably offer the illusion of a more responsive server, so i might actually add your suggestion to the game... thanks! :-)

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Sync is not a major problem, since movement-post-teleport type updates will be rejected automatically (since the client would effectively be requesting a re-teleport that far exceeds the maximum velocity).

This is true, however, I recommend slightly more sophisticated handling for teleports, just so that you can easily distinguish expected errors like these from unexpected errors that you would see if someone was cheating or there was a bug. Setting a flag on the server until the client has acknowledged the new position is one way.

Share this post


Link to post
Share on other sites
Instead of using fixed update intervals, you can also use 'ghost reckoning' to reduce data traffic. That is, the server extrapolates the client position. As the client knows what extrapolation the server uses, it can compute its 'server position'. The client only sends its position if the error between client and server position becomes to large.

Share this post


Link to post
Share on other sites
Quote:
Original post by dietepiet
Instead of using fixed update intervals, you can also use 'ghost reckoning' to reduce data traffic. That is, the server extrapolates the client position. As the client knows what extrapolation the server uses, it can compute its 'server position'. The client only sends its position if the error between client and server position becomes to large.
Thanks Diet; that's essentially the approach in #3, above, except that its the server that informs the client when the positional error hits a threshold, rather than the other way around.

Share this post


Link to post
Share on other sites

This topic is 2652 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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