Wednesday, March 19, 2008

Lag Compensation

Continuing from yesterday… I’ve discovered several very interesting articles on lag compensation in real-time environments. The first is from the author of the Unlagged! mod for Q3A, the second a discussion of lag compensation network transmission protocols in the Source engine, and the third is a higher-level conceptual discussion of lag comp. in terms of client/server synchronization, by Valve Software.

Unlagged proposes a pretty simple addition to normal dead-reckoned non-delayed broadcasting, by using historical data to check for weapons hits. This method produces a result that is fair to sending clients, but may seem inexplicable to receiving clients. A client aims for his enemy, pulls the trigger, and hits, but from the victim’s perspective he may have dodged the shot. Clearly, this is a good first step but not the whole thing.

Valve’s documents were much more interesting. They proposed having the client-server simulation as usual - but have the client render a fixed timestep behind the server. That way lag compensation discrepancies can have time to blend and interpolate before being presented to the user, and that clients do more interpolation than extrapolation, which is always good for everyone.

Extrapolation involves predicting the movement of objects in the future. While this is generally accurate, if the player is moving erratically it can actually be quite far off. In the Source implementation the only thing that is extrapolated is the player’s own movements, which by all accounts is fairly accurate. All other movement, including other players, is interpolated between already-known data, hence why the entire engine renders 100 ms behind the actual simulation.

I put together a little diagram with a test scenario and ran it through my head. This works rather well:

Tuesday, March 18, 2008

First Post Redux

My last blog kind of fell apart, mostly because my life really isn’t that interested, and the interesting parts aren’t really safe for public consumption ;) Here is my newest attempt to maintain some decent documentation of what I’m doing, and for a change I’m going to focus it more towards my game development and technology-related thoughts as opposed general life goings-on.

In this issue of the Amazing Spud Adventures…

Networking in Real-Time

This is a topic that’s been on my mind lately. What is the best way to network in a real-time environment? For pab (my, and a couple others’ pet project) multiplayer isn’t exactly a focus, but for completeness and versatility’s sake I’d like to include networking capability into pab’s engine, which has brought up a few interesting points.

Entity Replication

This is a pretty simple thing to do, and is more of a code reduction issue than it is a true networking issue. An effective game engine should not force game-level coders to craft their own replication packets, nor should it expect said coders to invoke entity replication manually. Such low-level shenanigans are better left to the engine itself, both as a way to reduce error and reduce code complexity at the gameplay level. I’ve been thinking about ways to best implement this, but it leads to the next issue.

Tweening, Lag Compensation, Movement Prediction, and Server/Client Precedence

Say a nearby player’s position is updated every 20ms to avoid flooding your connection with unecesarily frequent updates, what happens in the real-time environment between entity updates? Clearly the player cannot “snap” between server updates. The obvious solution here is to have the server update not only position, but also heading and velocity of mobile entities. This will allow the game to tween the movement of said entity between updates. In heavy (or inconsistent) lag environments, though, this breaks down pretty quickly. If the object is traveling along a curved path (most likely), a straight tweening method with heading and velocity simply will not do.

Alternatives including cubic spline fitting, to best predict the movement of the object in the short term, project its course based on historical data over the last 4-5 updates. This will suffice for the vast majority of movement types, but is also not perfect. What if, for some freak reason, the server update indicates a position that is completely off from client-side prediction? Logic will dictate that server updates take precedence and the object will error-correct and “snap” into the new position. But even the best lag prediction methods are far from perfect, and small discrepancies will occur between client side prediction and server update. In this case do we still snap? Or do we attempt some sort of blended tweening to get the entity into the right position without such a noticeable and glaring motion?

Food for thought I guess.