Alright... So you might have seen me around a few threads here that mention the perspective of developers on The Framerate Police. While the discussion here was mostly civil and reasonable, on other sites people often try to deceive others by spreading misinformation about 30 FPS. And even innocent posts can cause can misguide people, because of a lack of context. So I've decided to take on the task of explaining everything I can about what the lock is, why people use it, how hard it is to work around and how to not get fooled by people saying scary technical words.
I don't want anyone to get the wrong impression about my experience so here are the basic facts about my background. 4 years of study in software engineering, 1.5 years of work in a big software company, worked on projects for substaintial clients (can't disclose the names), fields of work include CAD and e-government. Haven't actually released a game, gamedev is only my hobby. Currently I am working on a simple engine from scratch. While that may seem wasteful seeing how easily accessible things like Unity or UDK are, I do believe that knowing the inner workings of an engine is a requirement for someone who wants to be a skilled gamedev.
(This is not bragging. The point of this paragraph is to show that while I am a somewhat competent developer I am not yet a gamedev)
The Main Loop and the Frame Dependence Problem
So every developer (assuming he's not using an existing engine) begins his first game with something called The Main Loop, a series of actions which are repeated over and over again; basically this loop is the game in its purest form. If you simplify everything it comes down to three actions:
1) Get and process input.
2) Update game state.
3) Render the frame.
Unfortunately, if you try to write code following those three steps you will get a game that runs at different speeds depending on how high your FPS goes. This creates many obvious and less obvious problems, which are not as important for the discussion. Let's take a look at some solutions.
Solution #1: FPS lock.
This is the easiest and probably the worst solution. You can lock your FPS and make everything run at the same speed. Simply do the three actions and let your program sleep or gather input until the next frame needs to be drawn. This approach is the usual reason for the 30 FPS lock.
Good: extremely easy to code.
Bad: the framerate is locked, any slow down in framerate will lead to the game going into slow motion and may require any time based input to be slow motion too (something like holding down the button for a set period of time).
Very bad: Ties your rendering to pretty much all other logic, which breaks many principles of good design, which in turn will make the code more difficult to write as the time goes on; can cause big problems with the multiplayer if one of the players starts dropping the framerate.
Solution #2: Delta time.
This solution is also quite simple. Don't lock the framerate, just measure how much time passed since the last frame and operate based on that. Let's say a car has a value of speed, then you can multiply that speed by the time that passed since the last frame and find how much distance the car made. Simple, right? Not quite.
Good: Your framerate is no longer locked. The solution is still mostly simple. You will always get the best performance possible on the machine.
Bad: Rendering and logic are still somewhat tied, the time of the frame is a variable through all of your calculations.
Very bad: Well, first of all, calculation takes time. It takes time to calculate the position of every moving object in the game and do other updates too. That time is not included anywhere so while your car will move by (speed * frameTime) meters, it should've actually moved by (speed * (frameTime + calculationTime)) meters. In addition to that floating point numbers are unreliable. Every time you add, multiply or subtract two of the same floating point numbers the result will not be the same by a very small margin. Usually this is not a problem, but if your framerate climbs high enough the numbers will start getting smaller and smaller, which will mean that the error will become more and more substantial. All of that may lead to the developer once again locking the framerate. However, this approach can usually maintain a higher lock (for example 60 FPS) and will not cause the game to completely break if someone messes around with the ini files.
Solution #3: A double loop.
This is the approach that most modern engines take. Basically it comes down to making two loops. One of them is run every X milliseconds, the other one runs every frame. The first one updates the logic, the second one renders your game. There are different ways to achieve this. Some developers might tell you that this requires multithreading (a technique which causes the computer to quickly switch back and forth between different tasks to make it seem like they are run simultaneously), some may even say that you need multiple cores (which actually allows to run two tasks completely simultaneously) to do something like that. They will then go on to tell you how difficult multithreading code is to debug, which is true. The truth is, you don't need any of that. Unity, for example, runs both loops in the same thread, no multithreading, no multicore shenanigans.
Good: Best approach in terms of design. Your logic has no longer anything to do with your FPS.
Bad: The two loops are usually set to different refresh rates. This means that your game may still only take input 30 times per second even if the framerate is 60. Also this approach is not easy to code if you are a starting developer.
Very bad: You need to very carefully consider how often you run the frame independent loop. If you set it to something like 240 Hz and it can only manage 60 then a lot of your logic may break.
So there you have it. Everything about how framerate and update rate can be related (or unrelated). My personal message to all the devs out there: "Do not compromise!" Don't settle for the lock, nor for the delta time, aim for total frame independence. If you can't manage that then you won't be able to manage much more difficult tasks in the future. Listen to what code guidelines tell you and learn from everyone who struggled with these problems in the past.
And now for the final part.
The Great List of Bullshit:
1) Optimization is very difficult and some devs just don't have the time and resources to make sure their game maintains a stable 60 FPS.
As with many statements on this list, this one is technically true, but has nothing to do with FPS locking. If my PC can't run your game at higher than 30, that's an optimization problem. If your game is locked at 30, that's a design problem. There is no reason not to provide the end user at least an option to unlock framerate or set a higher cap if your only concern is optimization.
2) Because of certain early design decisions sometimes 60 FPS is not achievable.
Technically true. Only here in software engineering we don't call those things just "design decisions", we call them design mistakes. Basically when people say this they are referring to everything I've described above.
3) Not all engines have the capabilities to unlock FPS.
First of all, an engine is not a sealed box, at least most of them aren't. If you need some piece of functionality, write it. It can be difficult to do, but still not as difficult as doing it from scratch. Secondly, if there is absolutely no way you can incorporate unlocked framerate into an engine, why are you using that engine to begin with? Thirdly, most modern engines have tools for this. The most famous one is Unity; it basically has the double loop set up already (functions Update and FixedUpdate).
4) There are artistic reasons to locking a game at 30 FPS.
Okay, I'm not going to argue that there aren't any reasons for that. I'm not much of an art person. However, there is one thing that I know for sure. If your game is designed in a proper way, providing an option to unlock framerate or at least switch to a 60 FPS lock should be trivial. Even if you expect your game to only run at 30 FPS, the lock is still a bad idea.
5) All of this is super difficult and costly.
It's not that costly, but it's difficult. Which is why game engines like Unity implemented it for you ages ago.
And there you have it. I don't expect most people to care about this. In the end, everything that doesn't affect the user doesn't exist for the user. However, some of you may have thought something like "Should we really expect 60 FPS from small development teams? How much money would it cost? Will we make good indie devs leave by wanting higher framerate?" Hopefully now you have the answers to at least some of your questions.
EDIT: Alright, this got a lot of attention and many people are saying the same things, so I feel like I have to clear a few things up:
1) I was a bit unfair to the delta time method. It can work and it can work almost flawlessly. The example I've given is just describing a very trivial implementation of delta time. That implementation may lead to a soft lock in the future. I just felt like providing the proper implementation was way too technical. But you are right that I should have at least mentioned that it exists.
2) The double loop is not described fully. The physics loop still needs to either be locked at a certain refresh rate or have its own delta time.
3) There are often more than two loops in the "double loop" method and they all may have different refresh rates.
4) This is not a complete explanation of a game engine!!! Please understand this. I was never trying to give a complete picture. Hell, this is not even a complete explanation of the main loop. My goal from the start was just to give people the information to fight those who spout technical bullshit. I was aggrevated by people who didn't make any sort of sense, but tried to hide behind smart words they were using incorrectly.