Advertisement

Planetary Annihilation networking

Started by December 09, 2014 05:01 PM
2 comments, last by gfxgangsta 9 years, 11 months ago
I recently came across Forrest Smith's excellent blog post:
It definitely goes into some of the networking concepts/algorithms/formats they used for the game. But some aspects weren't immediately clear to me. I was wondering if someone could provide some additional insight.
1. They mention the server ticks at 10fps. Do they mean that network updates are sent 10 times per second, or do they mean the server simulation loop runs at 10fps (and the network update is coupled with it)?
2. I think the concept of "curves" is pretty cool... when applied to positions for example, they only send *new* keyframes and avoid sending redundant data. However, after reading I wasn't sure if they generate new keyframes at 10fps too, or if they have a different rate for generating those. I know special events like collisions can also generate keyframes, but I didn't understand if keyframe creation was generally done on each iteration of the game loop.
3. How does a client smoothly go from one position to the next? The server generates keyframes, but by the time the client receives them, they're old. Let's say the last packet on the client was generated by the server at t = 0.5 and received at t = 0.6. When the client's game loop runs, t = 0.67. How does the client compute the position at 0.67? Is it just extrapolating using the line equation (where the "true" line segment is from t = 0.4 to t = 0.5)?
4. What if a unit stops? Based on the client's keyframes, the unit would continue to move. I'm thinking they can send at most one redundant keyframe (so the curve is now a line with two identical y-values), or they could send a "stop" pulse curve (one of those immediate events they talk about). Thoughts?
5. Speaking of pulse curves (instantaneous events), it seems like the client would just receive N of these during a server update, and process all of them on the next tick (because they're instantaneous on the server, but they're already old when they're received on the client). Or, is the server somehow generating these in advance? For example, when a unit will fire, the server knows that the unit fires two shots, so it can send both shot events right away. But the first shot would still be old, wouldn't it? And, depending on lag & the time between shots, the second one might be old too.
6. Based on the previous "shooting" example, how would health be in sync with the attack? If health is a separate curve, the health packets and the shot packets might reach the client at different times (or, if the client plays the shot animation but has already received the health keyframe)... this means health number and visual attack won't be in sync. Would they wait and send the health keyframe along with the attack keyframe? Or, would they send both in advance, and the client is responsible for "playing" them at the same time?
The original post is great, I'm just fairly new to networking (but fascinated by it) and would appreciate any help in making more sense out of this.

The PA tech is actually a very mature tech that started with Supreme commander (The 10 hz update rate concept, with seperate loop running for animation/UI)

The simulation runs at 10 hz, everything else runs "normally". Things looks smooth because the part running "normally" renders the deltas for movements/turning etc. Also, the game is lockstepped, so you're see'ing the "past".

Keyframe creation is done as input is given that will change the simulation, if I understand it correctly.

Lockstepping in PA's case means that what you're see'ing is a few frames old, which is enough time for the simulation to solve the issues (for example, calculating deltas of movement of 2 units crashing into each other is resolved and sent as a keyframe of a collision, instead of that delta value rendering for you.

They're old on the client as well, however, the client is viewing older simulation data.

Lockstep networking solves all sync issues that you mention. The server only proceeds when all players are informed of what happened. The server then waits for that to render.

Advertisement
1. They mention the server ticks at 10fps. Do they mean that network updates are sent 10 times per second, or do they mean the server simulation loop runs at 10fps (and the network update is coupled with it)?
Yes. The servers simulation loop (the server's frame rate) is 10hz and network updates are coupled with it. However, they go to some effort to make sure they don't send updates for any entities that haven't changed.
2. I think the concept of "curves" is pretty cool... when applied to positions for example, they only send *new* keyframes and avoid sending redundant data. However, after reading I wasn't sure if they generate new keyframes at 10fps too, or if they have a different rate for generating those. I know special events like collisions can also generate keyframes, but I didn't understand if keyframe creation was generally done on each iteration of the game loop.
They would create new keyframes at 10fps, sometimes more than one keyframe (as in the bouncing ball example), but for many (probably most) objects, there wouldn't be a new keyframe to generate. Any object standing still sends no keyframes.
3. How does a client smoothly go from one position to the next? The server generates keyframes, but by the time the client receives them, they're old. Let's say the last packet on the client was generated by the server at t = 0.5 and received at t = 0.6. When the client's game loop runs, t = 0.67. How does the client compute the position at 0.67? Is it just extrapolating using the line equation (where the "true" line segment is from t = 0.4 to t = 0.5)?
The situation where t=0.67 when the latest receipt from the server is t=0.5 shouldn't happen in the general case. The client will try to keep itself at the server time + the average latency + a bit extra. Most of the time you're playing you will be interpolating toward the latest receipt from the server. Occasionally with a network hiccup you might accidentally catchup and overtake, I don't know what they do in that case. Probably they allow a little bit of running ahead with extrapolation, but if you end up too far ahead the time on the client probably slows then stops so you're not seeing too much made up stuff.
This also answers questions 4, 5, and 6, I think.
@Conk - From the article, it sounds like a pretty different approach to Supreme Commander. It isn't lockstepped at all, it's completely server-client in its approach
PS - Good article, thanks for sharing it gfxgangsta


The situation where t=0.67 when the latest receipt from the server is t=0.5 shouldn't happen in the general case. The client will try to keep itself at the server time + the average latency + a bit extra. Most of the time you're playing you will be interpolating toward the latest receipt from the server. Occasionally with a network hiccup you might accidentally catchup and overtake, I don't know what they do in that case. Probably they allow a little bit of running ahead with extrapolation, but if you end up too far ahead the time on the client probably slows then stops so you're not seeing too much made up stuff.

This also answers questions 4, 5, and 6, I think.

Thanks for shedding some light into this. I guess that makes sense... if the client gets too far ahead of the server values, that's when you could start seeing strange behavior or harsh corrections.

For question 4, then I guess stopping could happen naturally when you've reached the endpoint of your curve (or the "not too far ahead" point).

This topic is closed to new replies.

Advertisement