Lockstep RTS: in between updates for higher visual framerate?

Started by
10 comments, last by suliman 10 years, 2 months ago

Hi

Im doing a lockstep-based RTS which steps every 50ms (20Hz). I might have to go up to 100ms steps (10Hz). In my lockstep-update i do everything including moving/rotating units and projectiles. As you may suspect this looks rather choppy.

So i plan to add a in-between (between locksteps) update and run it every 20 ms (or whatever) and update positions etc to make it look more fluid. Is this a good idea? Should this update only change variables that are strictly for drawing purposes such as:

pos // unit real pos used for collision and all simulation important stuff, updated in lockstep

pos2 // used only for drawing, is updated in-between locksteps

Example

unit speed is 4 pixels/lockstep but i run the in-between update which moves it 1 pixels per update, and pos2 resets each "real lockstep" to ensure no desync between players.

Or do i dare run a complete update some set number of times between each "lockstep update" (the only update where player commands are processed)?

Thanks!
Erik

Advertisement
You can make a difference between "displayed position" and "simulated position."

Specifically, you can update the "displayed position" each time you render (at whatever the render frame rate is,) but update the "simulated position" only during your lockstep update tick.

You can interpolate the display position between the previous and current simulated positions. This will add some display latency, but won't display anything un-truthful. This is great for RTS-es.
Or you can use a forward extrapolator, like the Entity Position Interpolation Code, to predict what the position/orientation will be for an object, and display to that, which will perhaps somewhat overshoot positions etc, but give the illusion of less display latency.
enum Bool { True, False, FileNotFound };

Yes i understand the two variations but in general this is what needs to be done? (and the typical way to do it?)

I believe that the most typical way to do it is to interpolate smoothly between 2 lockstep frames for rendering.

In the original post, you suggest having some special "in-between" sim steps that run at a higher, but still fixed, update rate. I think this isn't as good as the interpolation approach, as the interpolation approach allows you to smoothly render at any framerate.

cool.

stuff like particles systems, would they not mess up the random seed (that i set at gamestart so each client gets the same random numbers) since they are framerate depandant (and may therefore use different amounts of random numbers) ending up in desyncing the clients? Havent investigated this yet.

Thanks!

Usually you would have a separate random number generator for the lock-step part of your title than you use for anything that can be frame-rate dependent.

(double post trying to edit my post)

So i plan to add a in-between (between locksteps) update and run it every 20 ms (or whatever) and update positions etc to make it look more fluid. Is this a good idea?


Your deterministic update can work however you want. If the way you execute one "lockstep" update is to step your game exactly 2 or 4 or whatever simulation steps forward, that doesn't mean you'll go out of sync. If you decide to calculate/present those 4 steps over time to the user as a form of interpolation, that's possible too. It sounds like, for your RTS, you would want to be to configure your lockstep and a multiple of your simulation's frame rate.



Or do i dare run a complete update some set number of times between each "lockstep update" (the only update where player commands are processed)?


Yes.
In a typical RTS, the player commands are available for steps ahead of time -- you cannot proceed to step X until the commands are available for that step.
You can bundle multiple different step commands into a single packet. Thus, even if your network rate is 10 Hz, you may use a 60 Hz simulation AND INPUT rate, and simply pack commands for 6 different ticks into a single packet, and then queue them on the receiving side for the right tick.
enum Bool { True, False, FileNotFound };

Would that be useful? If i receive 6 commands each 100ms (how fast will the player click?) how does it make sense to spread them out to each 20ms on the client side? You mean i log when they were actually clicked by the player in the first place? I dont think you need that kind of resolution on the commands in an rts.

This topic is closed to new replies.

Advertisement