EPIC and Time

Started by
11 comments, last by hplus0603 14 years, 10 months ago
Hi. I was going to use hplus' EPIC extrapolator, and I have a question about the synchronized timer it works on. I haven't done networked interpolation before, so I'm learning. I also couldn't find any real examples on network clock synchronization (oddly...) Here's my thoughts so far, and I'd like some feedback on my approach. - Server starts, and begins a ticker (from 0). - When clients connect, they are told of the server ticker, and begin their own ticker to match the servers (though they don't account accurately for latency until...) - Each positional update from the server includes the time it created and sent the packet. - The client will average latency based on the response time from the server, and try to keep its own game clock in sync with the servers (I haven't decided on acceptable variation yet; though I've read hplus saying less than 100ms should be sufficient). So is this what it takes to make EPIC happy with a timer? It seems EPIC takes a local time argument and the packet timestamp, but if the clocks are synched very closely... is that a problem? It must not be too complex since I had trouble googling any kind of real demo or article on a simple, but precise, network clock schema. I did see a lot on NTP, but I'm not sure if that's overkill or not. Is that a recommended method for time sync? Calling out to a 3rd party time server? Thanks in advance for any responses...
"Creativity requires you to murder your children." - Chris Crawford
Advertisement
EPIC (and interpolation in general) wants the time to be continuous, relating to the time stamps used, and smoothly varying. The role of a forward extrapolation library is to provide an estimated value for a property at time t2, given some previous values and times (say t1 and t0). In general, you want t2 to be in the range of (t1, t1*2-t0), and you want the spacing of t0, t1, ... to be as even as possible (ideally, fixed-size time steps).

How you accomplish this varies based on your networking. Typically, the server will provide a timestamp with each packet it sends, and the client will use an estimation of round-trip time and its local timer to match up the two. Typically, you will want to make adjustments in rate, rather than in position, after the first sync-up, so that time does not make discrete jumps.

Perhaps I should write a simple library for this task, too. It's not that hard, but it also seems to trip up a surprising number of people. You seem to have it mostly right, though: t0 and t1 come from "server time of execution" and t2 is the client's estimation of "server time at rendering," and as long as these are "close" and advance at the same rate, it will work out. Most important is to make sure that t2 >= t1, or you'll get weird behavior.
enum Bool { True, False, FileNotFound };
Quote:Original post by hplus0603
How you accomplish this varies based on your networking. Typically, the server will provide a timestamp with each packet it sends, and the client will use an estimation of round-trip time and its local timer to match up the two.
Sounds reasonable.
Presumably what you really want to know is the time for a server packet to reach the client (and vice versa) rather than a full round-trip, except with most internet connections it ought to be fairly close to half the RTT.

How do you deal with asymmetric connections though?
Not that I can think of many examples of the latter. Satellite internet or multicasting setups perhaps.
Thanks for the prompt responses!!!

Yes, my update times are fixed (~200ms right now, but may change). My little app is using event-based TCP right now, but I may switch away from that for the positional updates (it's quite nice for other things and more periodic behavior). Plenty of fun and tweaking ahead of me, network programming is still kind of new to me, so I'm having a good time figuring things out.

Thanks again, all.
"Creativity requires you to murder your children." - Chris Crawford
Quote:How do you deal with asymmetric connections though?


You don't. Time is a way of making sure that things happen in the right order. As long as you have a proper partial ordering between events, the exact time does not matter.

enum Bool { True, False, FileNotFound };
Quote:Original post by hplus0603
Quote:How do you deal with asymmetric connections though?


You don't. Time is a way of making sure that things happen in the right order. As long as you have a proper partial ordering between events, the exact time does not matter.


I guess the concern is the skew of really awful upload, but fast download?

When the client could potentially receive far more updates than it sends?

If that's the case, would the replication for other clients (who aren't as slow) get funky because the server has very old data for the slower client? Granted they'd all be stepping on the same simulation, but really slow upstream clients could almost have an advantage because of warpy-jittery movement everyone else might see, but they necessarily do not?

Maybe this is a topic for another time, but it's something that I just considered.

For example, if you've played World of Warcraft and PvP... some players are just all over the place, it's almost impossible to fight them in an ordinary fashion. Sometimes I wonder if they intentionally slow their trips up so they can have a one way advantage?

Would the solution to that be to simply kick people who update tremendously slow?
"Creativity requires you to murder your children." - Chris Crawford
Quote:Original post by catch
Quote:Original post by hplus0603
Quote:How do you deal with asymmetric connections though?
You don't. Time is a way of making sure that things happen in the right order. As long as you have a proper partial ordering between events, the exact time does not matter.
I guess the concern is the skew of really awful upload, but fast download?

When the client could potentially receive far more updates than it sends?

If that's the case, would the replication for other clients (who aren't as slow) get funky because the server has very old data for the slower client? Granted they'd all be stepping on the same simulation, but really slow upstream clients could almost have an advantage because of warpy-jittery movement everyone else might see, but they necessarily do not?

Maybe this is a topic for another time, but it's something that I just considered.
This effect happens even in commercial games. In particular, if I turn on bittorrent while playing TF2, I can cross the map to melee snipers with impunity - the torrent causes my connection to lag, and the lag causes me to jitter so much on their screens that they can't hit me.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Is EPIC a little skewed toward faster updates? It's quite warpy with updates around ~200-250ms, much less so with 100 or lower.

I mean, naturally, more updates are better, but I'm trying to aim for a something in the ballpark of 150-250ms for position updates.

All testing on my local machine so packet loss isn't an issue. I'm just curious if I'm trying to hit a finish nail with a sledgehammer here... or maybe my timing is off. Does it sound like I may be stepping things incorrectly?

Sorry for my newbie ness. I can try to post code if it matters any, though it'd be all over the place (you know how quick projects end up...)
"Creativity requires you to murder your children." - Chris Crawford
If you get updates every 200 milliseconds, and the transmit delay is 200 milliseconds, then EPIC, or any extrapolation library, will give you positions that are up to 800 milliseconds of travel time off: 400 for the update rate delay and send delay, and 800 for the travel that the sending client is doing in the meanwhile. Yes, I would imagine that that could be seen as "warpy" if you travel in a zig-zag manner.

Also, because it is dependent on time, poor clock management will cause problems as well.

If you want to totally eliminate warp, then you display objects time delayed instead, so you show them at locations where you know they have been -- but, in that case, they would be 400 milliseconds behind "current" even when "current" is traveling in a straight line.
enum Bool { True, False, FileNotFound };
You know I think how bad it would be for them to be behind in time, then I consider 400ms (which is a high end of the spectrum estimation, I guess) and realize it's a very little time to human perception (but quite long to a computer).

Is there a particular downside to running all game clients on that schema, where they only display positions they have already received? Would probably hurt some people's reaction time in a twitchy game, but in a more laid back setting like an RPG, maybe not so much?

Harumph. For as "fast" as World of Warcraft appears, it's run on a TCP event based system (mainly), and since my wife plays next to me I've studied moving and making actions and notice I'm always almost a second in lag on her client than I am on mine (where obviously my actions appear instant).

Then again WoW, like Diablo 2, isn't real finicky about where you're actually standing. As long as you're within like 10 yards of your true location, I could be in two totally different places compared to my client and hers.

Unfortunately true position is paramount to my design... Even extrapolation and the rare snap it might provide may not do. It kills me, but I'm strongly considering running all clients in the past, or simply doing fixed drawing based on updates (which sucks and is slow; Look at Clan Lord if anyone knows the reference; but there's no inaccuracy whatsoever in where anyone is standing).
"Creativity requires you to murder your children." - Chris Crawford

This topic is closed to new replies.

Advertisement