RPG MMO Style network movement

Started by
7 comments, last by Drew_Benton 14 years, 10 months ago
I'm using LE 3D engine and RakNet for my networking library. I'm wondering what would be the best approach in getting movement down over the network. It's a target based system so it doesn't need to be as accurate as a FPS. There will be no projectiles shooting or anything. The way I tried it, but it was pretty bad, was to send commands to the server and have them relay that to the clients. When I pressed the 'W' key I sent a MOVE_FORWARD command to the server. The server would then start the client on it's side moving forward. It would then send that command to all the other clients and they would start their version of that client moving forward. This didn't seem to work out all that great. It would get out of sync pretty easily. So I then put in place the server sending updates to everyone about everyone's position. On the clients I said if the position was off by so much snap to place. This lead to all sorts of warping. The way LE works with it's player controller is that you just supply a speed and rotation value and it goes in that direction. You don't specifically move the player controller with positioning because them it kills the physics it has. I don't care all that much about physics either. Just a basic jump, falling, and colliding is pretty much all there is. I don't wish to be able to send the player in a specific direction, but even if I did LE uses Newton which is supposed to be deterministic so given all values equal I should get the same result on the client as the server. So any pointers or ideas on how to make smooth movement for an RPG MMO?
Advertisement
For an RPG like that, when the player is moving, I would send a "position and velocity" (or maybe just "position") packet twice a second, and the server can forward it to interested clients. When the client receives the packet, it can use interpolation to move the character towards that position, or it can use extrapolation to place the character at the position and move it in the given direction, or some variant thereof (such as the linear spline in EPIC).

One alternative is to calculate "targetPos = packet.position + packet.velocity * 0.5", and calculate "targetVel = (targetPos - currentPos) / 0.5," and update the velocity of the displayed character to that target velocity. As you can see, the local physical simulation will then make it so that the player is at the predicted next position, at the predicted next packet receive time.

Deterministic simulation in a physics engine for an MMO is a lot harder than just using a deterministic physics engine -- all the inputs must be the same, across all machines, which means that the positions, orientations, and the order of adding entities (!) must be the same, across all the clients. Generally, in a system where players can come and go at will, that's not achievable. If you want to do deterministic physics, you have to go about it a different way, and it ends up being very complex.
enum Bool { True, False, FileNotFound };
Quote:
For an RPG like that, when the player is moving, I would send a "position and velocity" (or maybe just "position") packet twice a second, and the server can forward it to interested clients. When the client receives the packet, it can use interpolation to move the character towards that position, or it can use extrapolation to place the character at the position and move it in the given direction, or some variant thereof (such as the linear spline in EPIC).


I'm trying to figure out how I can do this with the controller object the Leadwerks engine gives us. It handles all character movement and physics on that character. All you do it pass it a speed value, strafe value, and a rotation value and it will rotate to that rotation and start moving either forward given a speed value or strafe given a strafe value.
If that's the controller you have, then I would attempt the second option I suggested: Calculate where the dead reckoned entity will be half a second from now, and point the current entity in that direction, with the appropriate speed to reach that position in half a second.
enum Bool { True, False, FileNotFound };
What about making waypoints with the position updates? Then I could rotate the controller to the waypoint and start moving it. When I reach the waypoint it goes onto the next one. So basically each client would have a list of waypoints and when it gets updates it stores them in this list. The Update() method would start moving from waypoint to waypoint.
I have a question. Most games perform "client-based" movement. The server will just do sanity checks to make sure that the player doesn't warp/speed hack. Then if it violates the threshold, it would just disconnect the client and change it's coordinates to the previous legal coordinate.

This is a simple concept, however.... what about collision detection?

Quote:Original post by e_barroga
I have a question. Most games perform "client-based" movement. The server will just do sanity checks to make sure that the player doesn't warp/speed hack. Then if it violates the threshold, it would just disconnect the client and change it's coordinates to the previous legal coordinate.

This is a simple concept, however.... what about collision detection?


The games that do simple sanity checks usually don't do any server sided collision detection and rely on the client doing it. This of course is a real problem and usually exploited. I know quite a few F2P MMOs take this strategy.

Good games will run movement simulations on the server and also handle the physics and send the official results to the client. The client still runs the simulation, but only to hide the delay between between the client and server interactions. If the clients results are too far off from the server's the client will snap/warp everything where it should be for resynchronization.

The obvious tradeoff is the server has to do more processing work and upkeep, but it's a lot harder for a client to cheat the system. It is still possible if there are other flaws in the movement code and not enough sanity checks, but that's just how all development is, you can't program to stop all bugs without running into some first hand.

An example I've seen was a flaw in a game where a player could stack multiple speed increasing buffs. As a result, the server never checked the maximum moving velocity a player could travel and the movement simulation ran using high speeds and it all looked legit to the server while the player was clearly speed hacking in game.
So....

Perform simulations server-side (cons cpu intensive).
Also perform simulations on client-side and update any differences.

Won't doing this perform a sort of "rubberband" effect because of the latency?
The simulation on the server is for authoritative purposes in keeping the world as a whole valid and legitimate, if you so choose to go that route. A lot of games don't and while it's simpler to code, they end up paying for that decision later on.

The simulation on the client is simply to give a smoother presentation of the world as a whole. The server will always be ahead of the client in respect to everything but your own local actions that you have not yet been sent. Even so, until you do those actions on the server, you have not really done them, if that makes sense.

Because of that, you don't snap the client to the server's results, but you use those as guidelines to keep the simulation in sync and smoothed out as much as possible. If you ever load up two copies of a MMO and bring your characters near each other, you should notice most of the time the screens are not the exact same, but rather close approximations of the server state.

There are various degrees to this issue in terms of how in sync and up to date you want the client, so solving the issues just depends on what compromises you can make in your game. If you are using TCP and there is a short period of congestion, your client would be running a simulation much further behind the servers if you were able to compare the data in real time. With UDP, if programmed correctly, it might be easier to hide such events since the latest packets you are receiving are the most current even though you missed out on the previous states.

This topic is closed to new replies.

Advertisement