Advertisement

Server side events and world update

Started by May 25, 2015 08:43 AM
9 comments, last by hplus0603 9 years, 1 month ago

Hello everyone,

I'm proceeding with my prototype and everything seems to be working fine. Entity interpolation has still some small issues but I think it is something I can skip for now.

My server sends world state updates to the clients 15 times per frame, while the server updates at a fixed 30 frames per second. Some events might happen between the world state sync, and I was wondering if it is usual practice to send these events immediately or if they should be queued and flushed when I send the world update.

Thanks

That really depends on your specific game needs.

If you send "baselines" for world objects, and then send all events (movement, actions, etc) as they happen, you can end up sending the baseline state much less often, and save some bandwidth. If you send state 15 times a second, then the gain of sending an event sooner is smaller (but perhaps not zero -- depends on your game.)
enum Bool { True, False, FileNotFound };
Advertisement

For now I'm queueing events (together with the ticks when they happened) and sending them to the client in the "world update" packet; this way on the client it is easier to understand what happened in between two updates without having to decode this information by comparing the new and the old state.

I'm limiting the number of events to a very low number, to avoid sending too much stuff to the client. It seems to be working fine for now, but I'll know more as my prototype progresses :)

I just need to be sure the delta compressed world update + events always fit one packet I think, to make sure everything arrives together to the client.

I just need to be sure the delta compressed world update + events always fit one packet I think, to make sure everything arrives together to the client.


What is a "packet" for you? Could you use TCP, and not worry about "fitting"?
Is there an upper limit to the amount of events that could possibly be generated?
enum Bool { True, False, FileNotFound };

With packet at the moment I mean a UDP packet. Not sure I will be able to fit everything in ~1.4k, but I also want to avoid to split the world update in multiple packets and have some of them potentially arrive delayed due to the fact that I need to re-send them. But I think that's how it is for the most of the games? Or do they send the world update on an unreliable channel and hope for the best?

There is nothing that forces me in using UDP at the moment, but I already have a decent layer based on UDP and I'd rather stick with it unless TCP gives me something that I absolutely need. A game similar to what I'm prototyping (Realm of the Mad God) works over TCP and is working fine, although I believe they have partially authoritative clients or something similar to have such a smooth gameplay?

About the number of events, I have no idea at the moment. I'll see how the game goes and act accordingly. But I will encode in the world update only the events that I can't easily deduce by comparing the old world state and the new world state, so I hope to be able to keep the number low and also make sure they can be packed very tightly in the outgoing message.

Many games get away with sending updates in a round-robin fashion, perhaps prioritizing things close to the player. If one packet is dropped, then the next time those same objects are updated, they will be put back in sync.
Other games just send occasional state updates, and mainly send input commands/events, and run the simulation deterministically (or mostly deterministically) on client/server in parallel.
There's really no one true choice -- it entirely depends on the specific needs of your gameplay and "feel."
enum Bool { True, False, FileNotFound };
Advertisement

Other games just send occasional state updates, and mainly send input commands/events, and run the simulation deterministically (or mostly deterministically) on client/server in parallel.

This will be the cleanest approach IMHO, but I don't want to spend weeks of my time trying to get a way to fix the floating point issues that might come out of this approach (server and client will be running on different architectures). Maybe fixed points will help here? Or should I simply not worry about floating point issues as long as my game does not rely on complex physiscs?

If you are periidically resending server state, and server authoratitive, you dont need to worry about fp determinism. If there is a difference, the server will correct it anyhow.

You only care about determinism when doing a lockstep deterministic simulation, where the host never sends correction updates

TCP avoids many headaches, because with today's networks and wifi, some packet loss is guaranteed.

You want to avoid TCP when doing high frequency state updates which overwrite previous updates. For example, if you send full updates to 32 player locations at 30hz, you may be better off losing one via UDP then waiting for a retransmit via TCP.

However, a 10hz lockstep deterministic state simulation is better off using TCP because everything has to be recieved (nothing is redundant) and the game will pause anyhow if all clients are not in sync.

should I simply not worry about floating point issues as long as my game does not rely on complex physiscs?


No need to worry, because if something diverges, the next update for that object from the server will set it right again.
enum Bool { True, False, FileNotFound };

Hello, I've an additional question related to this topic.

I'm doing prediction on the player and interpolation on the server-controlled entities. This puts me in a situation where entities are a few milliseconds behind in time. When I receive a bunch of events from the server, I immediately apply to the ones that target the player, and I queue the ones that target the server-controlled entities; these will be executed in the future, as soon as the interpolation window reaches the right time.

By doing that though, I hit weird situations where, for example, I execute an "hit" event on the player, while the "attack" event from one of the entities is still pending execution (attacks happens instantaneously for now).

Should I simply queue also the events on the player, and execute them with some delay? Or is there another common way to deal with issues like the one I explained above?

This topic is closed to new replies.

Advertisement