7 ms·
> The joy of "discovering" this approach was short lived: This system is very well known in the game industry and is actually the keystone of games such as Star
by certeoun 5y ago
> The joy of "discovering" this approach was short lived: This system is very well known in the game industry and is actually the keystone of games such as Starcraft II or id Software engines !
Is it very well known in the game industry? I have trouble finding anything about it.
- meheleventyone 5y agoYeah extremely well known. Doesn’t mean everyone uses fixed time steps though or talks about it a lot when they do. But you’ll find the concept creeps up a lot in physic engines, deterministic networking/gameplay and in discussions of engine architecture amongst other places.
- certeoun 5y agoI am a little confused, isn't this a "fixed timestep"?: https://www.gafferongames.com/post/fix_your_timestep/ https://www.gafferongames.com/post/fix_your_timestep/ Fabien calls it "fixed timeslice". I find Fabien's solution much simpler. It is quite different to Fiedler's one.
- meheleventyone 5y agoWhether you call it a step or slice doesn’t matter, tick is another common term for the same concept. Fabien’s solution is mentioned in Glenn’s. Glenn just takes it a stage further afterward and allows the fractional time remaining to be accounted for when rendering.
- certeoun 5y agowhile (running) { static std::uint32_t simulation_time{0U}; std::uint32_t const real_time = SDL_GetTicks(); process_input(); while (simulation_time < real_time) { simulation_time += 16U; update(16U); } render(); } As I understand it, the inner while loop's is essentially playing "catch up" with the outer while. For simplicity's sake, let's assume that simulation_time is incremented to 1 in the inner while (simulation_time += 1U). Further, let us assume that simulation_time is 42 in the first iteration. Now, the inner while needs to execute 42 times until it fails the loop condition (42 < 42). On the second iteration, simulation_time is equal to 58 (42 + 16). The inner while executes (42 < 58) 16 times now. On the third iteration, simulation_time is equal to 59 (58 + 1). The inner while executes (58 < 59) 1 time. The real_time cannot stay the same, as it polls the number of ticks since SDL was initialized. So apparently, simulation_time is always smaller than real_time. (If for some reason, real_time isn't incremented in an iteration, then the inner loop will not get executed. However, I don't see a case where it can happen.) Now, inside the update function there is a position update akin to current_position += speed * 16U. Now with the above iterations: - The first iteration, causes 42 update calls (so current_position is updated 42 times as well). - The second iteration, causes 16 update calls. - The third, calls update 1 time. So we are advancing the position of something variable times. (We are also executing the inner while in variable amounts.) Maybe I am missing something here, but why doesn't the non-constant number of updates cause jitter? I really don't understand why it works at all to be honest. I am trying to understand it fully.
- meheleventyone 5y agoThe simulated time is incremented by 16ms per inner loop a roughly 60hz rate. You’re correct that the simulated time catches up to the real time. Just wrong about the number of sub-steps and how the timers proceed. Technically Fabian’s solution will likely run slightly ahead of real time because of the inner loop condition. You do get jitter from a changing number of sub-steps per variable step which is why you want to do things like the interpolation in Glenn’s solution. This is also why you still want to do everything in your power as a game developer to reduce the variance in real step size.
- certeoun 5y ago> The simulated time is incremented by 16ms per inner loop a roughly 60hz rate. You’re correct that the simulated time catches up to the real time. Just wrong about the number of sub-steps. Technically Fabian’s solution will likely run slightly ahead of real time because of the inner loop condition. Can't the inner while take 1 ms or 1 ns for an iteration? I don't see how the inner while's execution time is at roughly 16 ms. Okay, if my number of sub-steps is wrong, then I am really missing something here. Just trying to understand what exactly is wrong with my thinking. It is supposed to be so simple, yet I have real trouble understanding it currently. I am basically stuck now.
- meheleventyone 5y agoThe inner loop can take as little time as it likes to actually do the update but it is accounted in simulated time by adding 16 to the timer and accounting for that in the update by passing in 16 as the amount of time to update for. Real time is updated once at the start of the step then simulated time catches up in 16ms increments. So you get as many update calls as there are 16ms increments to simulated time before it exceeds real time. This is all very simple but also pretty finicky to think through. I’d replicate the code in the language of your choice and step through it.
- certeoun 5y ago
- TacticalCoder 5y agoYup it is well known since a long time. Fun fact: I discovered that technique myself around 1991 (and still have the ASM + C source code for the DOS game using it). The first time I remember it publicly described was on the GamaSutra website in a post-mortem for the first "Age of Empire" game. GamaSutra was/is a big deal among game devs so the technique became "famous" when that post-mortem was made. I wrote about it in a thread here called: "Why bugs might feel “impossible”" about two months ago and someone commented that the game TerraNova (from 1996) had a fully deterministic engine. BTW TFA say StarCraft 2 (2007) used the technique but Warcraft 3 (2003) was already using a deterministic engine. Save files for Warcraft 3 games (including multiplayer ones over the Internet) consisted in only recording the player inputs and the "tick" at which they happened. This make for tiny savefiles, even for very long games. So basically: several of us independently discovered that technique in the nineties. There may have been games in the eighties already using such a technique but I don't know any. https://news.ycombinator.com/item?id=27517074 https://news.ycombinator.com/item?id=27517074
- certeoun 5y agoWas it this article?: https://www.gamasutra.com/view/news/115711/The_Game_Developer_Archives_Postmortem_Ensembles_Age_of_Empires.php https://www.gamasutra.com/view/news/115711/The_Game_Develope...
- TacticalCoder 5y agoIt was more than 20 years ago so I don't remember: quickly skimming through it I don't think so. I still have emails somewhere I exchanged back then with the dev who wrote the article so I may be able to find the date. But in any case: the technique ain't new.
- certeoun 5y agoNow, I seriously question the notion of "the internet never forgets things". I wonder how much valuable knowledge got lost from that era (the 90s).
- hoseja 5y agoI don't think many game industry techniques are very well described in the open.
- fuball63 5y agoI learned about it reading the quake 2 sourcecode. In school or tutorial articles, they always teach the first technique, I find. "Delta timing" is what I knew it as.