Movement-algoritm over the network ?

Started by
27 comments, last by grumpymonkey 14 years, 10 months ago
Yo! I've been experimenting with some network programming lately and I've also been experience some huge problems.But my main-issue is how to do the movement so it will be as synced as possible over the network. And currently I've found one way to do it: On the client-side, I'm updating the position like "position += velocity * dt" where dt is deltaTime between every frame. Then, every 30th of a second, a package which contains player position and velocity is sent to the server which it self broadcasts this package to every client connected. And when a client receives a package, it updates the player position and the velocity to the given in the package. This movement is kinda smooth over the network, and very very synced, just a few millisecs out of sync. BUT. Is this a proper way of doing it? I mean, by feeding my server with 30 packages / s ? It doesn't sound very well to me... But at first, I was only sending that package when a player started to move and when it stopped, this caused a snapping to occur when the player stopped because the calculated position on the client wasn't the same as in the package for some reason, does anyone knows why? So my question is; How to do a proper movement over the network which is in "real-time" ?
Advertisement
I tend to just send key input to the server and let it simulate the game on its own. Then at a constant time it broadcasts its server state to the clients. (Using delta packets and such).

Then use an extrapolation and interpolation algorithm on the clients. If you look at EPIC in the Forum FAQ it might give you some ideas.

Also make sure that the server has an authoratative state and a fixed update step. I'm not sure from reading what you've written if that's what you have. If you're just letting clients send positions to the server and then the server just immediately sends them out then your networking is problematic.

There's some tricks you can do if your gameplay allows it. One being using inertia. So if your character moves in one direction have them ever so slightly come to a stop. If they try to start moving put a slight acceleration into it. I use that kind of idea in my tests and it works wonders.

Also is this TCP or UDP?
Quote:Is this a proper way of doing it? I mean, by feeding my server with 30 packages / s ? It doesn't sound very well to me...

In TCP never send packets at 30 times per second. Stick to 10 packets or less and throttle based on latency. (I assume your monitoring RTT between the server and client). In UDP I'm not sure what the normal packet rate is. My trick for it is to get it to work with the least amount of packets imaginable. Like try 5/sec. If it plays alright with that many then you should be fine.
Send the velocity vector of the player to the server. Don't send the actual key presses otherwise the server now needs to know about key mappings.

To explain the snapping you are seeing think of it like this you were walking to the left you and then stop you tell the server about this change in velocity. It takes time to get there. During that time you start walking to the right, you send a packet to the server informing it of moving to the right. After this packet is sent you receive the response from the server from when you stopped moving left and jump back to the point were you stopped moving left. You then receive a response from the server about moving to the right now depending on your implementation you may jump again.

This also means you game is open to warp hacking, since I can falsify my position.
Better yet, you'd probably just send an event-type, rather than a velocity vector. That's nearly as bad as the position-authority be given to the client.

Ideally the simulation authority is the server, not the client, so it wouldn't matter what the client was inter/extrapolating anyway (so it's own velocity is moot). Only which actions the user is making, and let the server simulate it from there.

By event I mean your coded packet to specify MOVE_FORWARD (or whatever) and the duration it was held down for the step between issuing an update. You wouldn't need to know the key bindings, just the action of the keys (moving forward, strafe right, jump, etc).
"Creativity requires you to murder your children." - Chris Crawford
the usual

http://gafferongames.com/game-physics/networked-physics/

Everything is better with Metal.

I am fairly new to this but here is what I do and I find to work pretty well.
You have a client and server that both host in broad terms similar simulation engines of the game.
All events are validated both locally and remotely. Local validation serves the purpose of having smooth interaction while upholding game rules this validation can be done fine grained. Remote validation serves the purpose of keeping game consistency at any cost.

When you wish to move forward you send a event to your local simulation if the event passes a pretest it is transmitted to the server. I transmit position, time and event type. When the server receives the event it also validates the event and if ok the event is activated on server also. Otherwise reject and post back to client.
Before this happens some time may pass and in order to keep the two simulations in sync as much as possible. So when another event happens that affects motion you again transmit the position, time and event.
This time the server can calculate the exact position of the player by delta_time * first_position and then validate it against the second position. If it is close enough (position +/- some_epsilon) then set the exact position and proceed otherwise do something to maintain consistency.

Basically only send information with regards of what you are doing or intent to do. Also you need some periodic synchronization to ensure consistency but this can be done at a low frequency.

Obviously there is a lot more to it when adding motion prediction etc. but this was the basic Idea I started from and slowly progressing :)
Quote:Original post by Sirisian
If you look at EPIC in the Forum FAQ it might give you some ideas.

Ok, so this is the actually algoritm I should use or what?

Quote:Original post by Sirisian
Also make sure that the server has an authoratative state and a fixed update step.

Before the server broadcasts, it saves all the variables of every player, so yes, the server holds the player positions and velocity as well.

Quote:Original post by Sirisian
Also is this TCP or UDP?

It's TCP!

Quote:Original post by Sirisian
Stick to 10 packets or less and throttle based on latency.

So I should actually send packages all the time while Im moving to the server, containing velocity and positioin ?

Quote:Original post by Oliii
http://gafferongames.com/game-physics/networked-physics/

Ok, is this for 2D-games as well as 3D ?

Quote:Original post by Stonemetal
Send the velocity vector of the player to the server. Don't send the actual key presses otherwise the server now needs to know about key mappings.

Im sending the velocity vector, not the actual key. I maybe didn't explain that very well..


And maybe I should explain a little more how my movement actually is done?
In the main-loop of the client, a function called move_player(dt) is executed every loop. dt is the deltaTime between every frame...
Then in move_player, it take the last velocity-vector received from the server, and sets the player position like "position += velocity * dt * 130", where 130 is 130 pixels/second to move.
Then every 30th of a second, a package to the server is sent with the calculated position, and the velocity. THIS package is not sent back to the client that sends it, it is only send to the other clients connected.

Then when the client receive a package, the client executes set_position(position, velocity), which sets a position- and velocity-vector for the player, given in the package.

--
But w/e.
The only thing I really need to know, is HOW I'm supposed to do in order to make it as good as possible. I looked at EPIC and didn't really get it how it works, and I also looked Glenn Fiedler's page which seems to have a good "algoritm".


[Edited by - pjuke on June 5, 2009 9:54:19 AM]
Quote:Original post by pjuke
And maybe I should explain a little more how my movement actually is done?
In the main-loop of the client, a function called move_player(dt) is executed every loop. dt is the deltaTime between every frame...
Then in move_player, it take the last velocity-vector received from the server, and sets the player position like "position += velocity * dt * 130", where 130 is 130 pixels/second to move.
Then every 30th of a second, a package to the server is sent with the calculated position, and the velocity. THIS package is not sent back to the client that sends it, it is only send to the other clients connected.


Bolded the part of concern. Why would you send the client position/velocity/anything to the server, which then would be relayed to other clients. To me, it sounds like a vulnerability.

The server should be simulating the clients and telling the clients where they ought to be. The clients would only interprate the data from the server and try to compensate to stay in sync... Never the other way around.
"Creativity requires you to murder your children." - Chris Crawford
If you don't worry about cheating, then sending pos/ori/vel 30 times a second is a fine way of doing it, and will result in smooth, natural gameplay. It will, however, allow for fly/teleport/aim hacks, should your players find your game interesting enough that they want to hack it.
enum Bool { True, False, FileNotFound };
Quote:Original post by hplus0603
If you don't worry about cheating, then sending pos/ori/vel 30 times a second is a fine way of doing it, and will result in smooth, natural gameplay. It will, however, allow for fly/teleport/aim hacks, should your players find your game interesting enough that they want to hack it.


Yeah, I know it works in the way I'm doing it, but I just thought that it maybe would be a better / more proper way of doing it than this ?

I don't really care about cheating, this game is for a final-test at my school in programming, so it's only for educational and fun purposes only :)

But again, is there any better way?
Because I've seen lots of ways, some are including a timestamp on the package as well to stay in sync or something. Im just curious!

This topic is closed to new replies.

Advertisement