Advertisement

Some precisions on movement

Started by October 08, 2015 10:06 AM
8 comments, last by hplus0603 9 years, 1 month ago

Hello there. I've been reading on this topic for some years now. Recently i started to program an action rpg game with online capabilities, but i always get lost when it comes to networking movement. Here are some of my doubts:

- First of all, many interpolation solutions takes for granted that packets will be received when a movement is produced. What if many move packets are collected and sent at the same time? This actually happens all the time. Client doesn't send player moves when buttons are pressed, they wait until packets are flushed.

- My entities have a speed property. I send this from server to client, but seems like client interpolation doesn't take them into account, which in my opinion makes my first question even more difficult to solve.

- How can i trust the player movement packet rate? The server will receive many of them at the same time, sometimes with different spikes of lag. I suppose that, in this regard, server cannot be too authoritative.

- How can i deal with different update rates between client and server? For example, if i want an entity to move 60 pixels per second, on client each update will move the entity less than in server. It seems to me that synchronizing both endpoints is like mission impossible.

-If possible i'd like to read some code examples. Souce multiplayer networking wiki has a lot of stuff but i cannot make mind.

Thanks, that's all for now. I have never seen the answer of some of these questions .

Don't send position/speed/whatnot from client to server, send the player's input to the server with a timestamp, and apply it the same way the client would, at the same gametime.

To compensate for lag either give clients' inputs a timestamp in the future (and delay application of those on clients as well), or have the client run in the future by having it simulate ahead of the server (client side prediction).

Both ways will result in the server receiving input-packets from clients with timestamps a bit before its own current gametime and apply them at the right time.

Both ways have drawbacks, such drawbacks indeed that not all types of games are possible with lag. There are reasons why some types of games are seldom seen online, like bullethell-shooters, 1v1 fighting beatem' ups and so on.

You should consider if your gamedesign allows for lag. Can players interact with each other, affect each other's movement? Then it gets tricky.

If players cannot collide with each other directly or indirectly and it's not PvP, things are easier.

Check gafferongames articles, and the comment sections there.

Advertisement
Regarding simulation and client/server authority:
1) Make sure you run at a fixed simulation step size / rate (20-30 steps per second is plenty for an RPG.) Every simulation step should have a well-known "step number" (which is related to but not the same as "time stamp.")
2) Have clients send inputs/commands/desires for each simulation step to the server
3) The server runs them at the designated rate
4) If clients send too many inputs/desires/commands per step, have the later commands overwrite the earlier commands, or drop the later commands once the "budget" is filled for a step -- your choice
5) If you believe the reason for the discrepancy is bugs in your client/network, work to fix it in code. If you believe the reason is hacked clients, then set a flag on the account, start failing trade/chat/group requests from the account after a few hours, and randomly auto-ban it some number of days later (to make it harder for hackers to know what exactly you're doing.)

Regarding interpolation:

My entities have a speed property. I send this from server to client, but seems like client interpolation doesn't take them into account


That's kind of hard to debug. Do you have code that's supposed to do this? Are you logging/printing/displaying this information somewhere?
enum Bool { True, False, FileNotFound };

To compensate for lag either give clients' inputs a timestamp in the future (and delay application of those on clients as well), or have the client run in the future by having it simulate ahead of the server (client side prediction).

i dont know how would work this. Then i should send at the instant every move packet? This seems to my like a lot. Also, i dont know how this solves the problem on detecting cheaters.

I'm open to more answers btw.

That's kind of hard to debug. Do you have code that's supposed to do this? Are you logging/printing/displaying this information somewhere?

Sorry, i didnt mean my interpolation wasn't working, but that in some examples i read you dont interpolate using this property, for example:

http://www.gamedev.net/topic/639568-network-interpolation-help/#entry5040786

You made a good point on simulating using the same rate in the server. I wasnt doing that exactly, but i'll take that into account.

To compensate for lag either give clients' inputs a timestamp in the future (and delay application of those on clients as well), or have the client run in the future by having it simulate ahead of the server (client side prediction).

i dont know how would work this. Then i should send at the instant every move packet? This seems to my like a lot. Also, i dont know how this solves the problem on detecting cheaters.

I'm open to more answers btw.

Well, i do send client-input every frame, and while it's a lot of packets, they are quite small. You can probably get away with a lower frequency, it does however increase the time needed to propagate inputs across the whole system. Also i send the current and some of the previous input-states, as unreliable packets, to account for eventual packet-loss. It's kind of frustrating when you fire off a good shot as a player just to have that one packet get dropped. I prefer sending multiple states in one unreliable packet over one state in a reliable packet, just because i had better results with it. Resending needs a timeout, maybe the packet gets dropped again...

The point about cheating is that the server just has to validate the player's inputs, which is easy. Letting players send their own position/speed etc invites cheaters to mess with those, while you can validate those too, it is more complex - and you can't really be totally sure until you would compare position/speed against the actual inputs - at which point sending them doesn't make sense anymore. Maybe you would easily notice a cheater sending forged positions that teleport him all over the map - but you probably wouldn't easily notice when the cheater just gives himself 10% more acceleration or something like that, or keeps changing his positions just enough to dodge some bullets...

Of course a cheater could send forged inputs, which would basically be a bot

That's kind of hard to debug. Do you have code that's supposed to do this? Are you logging/printing/displaying this information somewhere?

Sorry, i didnt mean my interpolation wasn't working, but that in some examples i read you dont interpolate using this property, for example:

http://www.gamedev.net/topic/639568-network-interpolation-help/#entry5040786

You made a good point on simulating using the same rate in the server. I wasnt doing that exactly, but i'll take that into account.

Simulating at the same rate isn't just a good tip, it's a must. Otherwise every frame simulations will be off a little between clients and server.

About the velocity, in the simplest case you just lerp between the old/new pair of all positional values including velocity. you do it for pos.x and your do it for vel.x. There are more elaborate methods of interpolation than linear interpolation, but given a high enough frequency of updates to interpolate from it should be good enough.

Advertisement

With simulating at the same rate i suppose it means that, when received the player input, i should simulate the movement using the same rate as the client, but here i have a problem. Movement update includes more forces, such as gravity or, say, magic. Which means i cannot simulate the player only when a move is received, i think no matter how i try there will be always differences between server and client.

Also, from the code example by Kylotan, i see that those entities are exclude from the physics system: you wont apply to them gravity or tile collision, but then this means even more packets sent. King Arthur's Gold for example uses extrapolation, and you can tell the client still applies physics to the entities because they collide with the map, and still is a fast paced game.

Then i should send at the instant every move packet?


You can bunch as many commands as you want into a single packet. The more you buffer, the higher queuing latency your movement will have.

i cannot simulate the player only when a move is received


Agreed! That's why you should simulate everything in a single "tick" operation, and number the "ticks" sequentially. When a client sends a command, that command should be marked with the "tick" that the server should execute it at. If the server receives "ticks" too late from the client, it can let the client know to increase its look-ahead amount (how much it adds to "now" to arrive at "expected execution tick number.")
enum Bool { True, False, FileNotFound };

Let me explain myself with an example: Client sends to server a "move forward" input. In that moment, the server updates the client. This move has the consequence of pushing the entity over a cliff. Now, obviosly gravity should come into play, but how do i compute it, since server has different timerate than client? I dont know, this is too complicated and i feel like im missing a lot.

Client sends to server a "move forward" input. In that moment, the server updates the client.


Don't do it that way.

since server has different timerate than client?


Make them the same.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement