Way back in the day, every game had its logic tied to its framerate – As anyone who’s ever tried to run an eighties PC game on a nineties PC only to see it run at 20x speed and completely unplayable can tell you.
But in the modern day this is less common. Generally the game keeps chugging along at the same pace, no matter how fast or slow the frames are being presented (unless, of course, everything is bogged down so hard that even the game logic is struggling)
And yet, you’ll still find a few. Any fan of Dark Souls who played on PC back when Prepare to Die edition first came to PC will remember how unlocking the framerate could cause collision bugs and send you into the void. And I recently watched a video of a gent who massively overclocked a Nintendo Switch OLED and got Tears of the Kingdom to run at 60FPS… Except everything was, indeed, running in fast-forward, rather than just being smoother.
This makes me wonder – Is there some unseen advantage to keeping game logic and framerate tied together? Perhaps something that only really shows on weaker hardware? Or is it just devs going “well the hardware we’re targeting won’t really go over this speed, and we don’t really give a fuck about anything else” and not bothering to implement it?
Tying these together is so much easier. The moment you start doing stuff independent of each other, you start needing to deal with concurrency and locking to prevent race conditions. You need to watch your locking strategy to prevent deadlocks. You need to synchronise state or objects may change position halfway through the frame. You need to sync up audio, video, input, physics, networking, and deal with the possibility that any of those hangs for a few frames for no good reason.
Concurrency isn’t free either, if you spread work that one single task can do just fine without performance issues across multiple tasks (be it on one single CPU core or multiple), you need to have tasks wait for each other to do certain stuff so you don’t corrupt your memory. That locking takes time, and you need to tweak your code not to lose too much time to context switching.
Many games will work faster with decoupled loops and concurrency, but there’s rarely enough time to implement them well. If you implement them badly, you get twice the amount of bugs at twice the CPU cores with half the debugging capabilities.