I was trying to debug an issue, but was having a hard time finding it in code, so I decided to do a debug run which forbids the game from moving unless I tell it to. The bug happened when the inventory screen opened, so I told it to break at the point in which I press the inventory button so I could view the script running. I was sitting there, stepping though script, and it blew my mind seeing how much it does in the time it takes the screen to open. I already knew all this to be true, but I'd never really bothered to watch it happen before. As I'm stepping it through each line of the code, I'm paying attention to the screen, going "Holy crap, it's gone through 300 lines of code and the inventory screen still isn't open!"
To those of you who have dabbled in software engineering or game development, this fact is a no-brainer. This is more for people who play games but don't have a clue as to what's going on. I mentioned, in a previous post, that there's stuff you don't see going on in literally every game you play. From Pong on an arcade cabinet to the latest Call of Duty, every single video game has both a visible and invisible layer.
"So what? There's script running. What does this have to do with anything?"
Sit tight, because I'm about to tell you, and this is where things get really wild. It's really cool, from a technical standpoint.
Before I get started, as per usual, I'm going to explain things without all the jargon and technical terms so that people who don't know what it all means can still follow along.
If you could see the invisible part of the game, chances are it would blow your mind. The uninitiated may assume that it does a few things every second, but that's not even 1/100th of what it does. Even things that only happen once per second, in game, are being tested and retested again and again and again in the blink of an eye.
My game runs at 60 frames per second, that equates to 60 'steps' per second. Each 'step event' is run each step, and each step event can have hundreds of lines of code and there can be several step events running at the same time. In the time it takes for a bolt of lightning to strike the Earth, the game you're playing has likely run hundreds, if not over a thousand different checks and processes.
Let's use my game as an example. Remember that inventory screen I showed?
I have no screen transitions programmed in, yet. So if you press the inventory button, this screen pops up instantly. It's nothing special, but the process may not be what you expect.
First, a black box is 'drawn', or rendered, over the entire screen, this is to mask the game screen in between one screen and another, in the event that the game slows down or fails to draw the inventory. Then, the background is drawn. After that, each of the inventory slots on the screen is drawn, one at a time. There are 60 in all.
When, and only when, all 60 of those are present it creates the blue box around each inventory slot, one at a time. Each of these blue boxes are empty, and each of them have their own strings of code that need to be executed the instant they appear before the game is allowed to move on to the next one. They all start out blank.
When they're all there, then one after another, each one is checked, one at a time, to see what item is meant to be contained within. It goes down the list of items that are possible to be held in the slot, and when it finds the ID of the item that's contained, it switches to display that item.
And finally, it creates the image of the character on the left, and initializes all of its important variables. Everything I just described, it does all that and more in the blink of an eye. It's so fast that you can't even see it. It looks like it pops up immediately. I wish I could show you, but since rendering is handled at the very end, you wouldn't even be able to see them all pop up one at a time if I slowed it down. They'd all show up together, regardless.
Some of you may have learned something new, reading this. If you have the time, I recommend you continue reading, because you're about to learn so much more.
Remember what I just taught you, above? How the game runs a ton of things in a fraction of a second? Well, that's where frame rate issues tend to spring up from. If there are too many things going on, your computer may not be able to keep up with the game's demand. This makes each step take longer to complete. If you have 60 steps per second and steps 2 and 6 have an excessive amount of scripts to run, it has to do those before it can move on, and if your computer can't process it fast enough, it may take longer for the next set of frames to render, which is part of the reason the frame rate drops. I can't go into depth on frame rate because it would take too much time, and I'd have to explain too many tangentially related elements, but essentially, the number one cause of frame rate issues is having too much for it to do in each step.
"Why is frame rate even an issue? Just fix it!" Yes, a good game has no frame rate issues. And a drop in frame rate at any point during normal game play is unacceptable, and I'm not trying to say we should permit it. But it's not so easy to just stop a game from slowing down. What some of you may not realize is, the game doesn't just have to run what you're doing at the moment. No, it runs EVERYTHING it's able to, many times a second.
It's very much like the engine of a car. Even when you're standing perfectly still, and nothing on the screen is moving, the cylinders are still pumping away diligently. What's it doing? Tons. Let's take an example script for instance:
if (global.PlayerHealth < 1)
global.PlayerLives -= 1;
This is something I made up on the spot. As you can see, it's color coded. The red part of the script, even if your health is full, is still going to be tested over and over and over. It will reach the red part, test it, see that it's not true, and move on. This is how 'statements' work. The code declares something, and tests the validity of that statement. When it comes back to it, it will test it again, and it will keep doing this until the script is no longer present or no longer accessible to the game.
Essentially what's happening can be read out like this: "Is health under 1? No, move on." It will only run the blue part if the red part is true. so unfortunately, there's no real way to tell it to stop checking the red section. Doing that could also cause delays in time-crucial events. So there's no real way to guarantee a game will never slow down, even on a state-of-the-art computer. Even if you used a call script (a script that doesn't run unless called), you'd still have to set up a trigger for that call, and it would still have to test that trigger, if the activation of the call script is automatic.
How does that kind of thing weigh down a game? Well, try out this experiment. Load up your favorite modern game, (no earlier than 2013) let's take Skyrim or Call of Duty Black Ops 2, and load it up. Doesn't matter if it's on console or PC, just load up a modern game. Now, provided it's not something like Candy Crush, or Angry Birds, go to a level or area. If you've loaded Skyrim, go to Whiterun, if you've loaded Black Ops 2, pick a relatively sedate level where you can just stand there for an extended period of time without dying. It doesn't matter what game you choose, these are just my examples. If you don't have the time for this activity, you don't have to play along. This is just for fun. For anyone taking part, before you read past this point, stand there a few minutes with the game unpaused, and take a good guess at what's currently running, script-wise.
Got your guesses? Good. If you guessed 'little to nothing is currently running' I'm afraid you're quite wrong. First of all, if you're playing a 3D game, the render distance controls are running, and if you're playing a large 2D game, like Enter the Gungeon, the activator/deactivator system is running. (It's essentially the 2D equivalent of render distance.) For those playing Black Ops 2 or Skyrim, you are running. Everything about your character is being handled. Idle animations, stats, spells, ammo, armor, the weapon you're holding. It's all being run.
For Skyrim players, the dynamic shadow renderer is running, the day/night system and weather system are running, for Black Ops 2, it depends on the level, because that game isn't quite as uniform as Skyrim, but maybe the weather is doing something, like raining, or the wind blowing the grass and trees. Whether Skyrim or Black Ops, there's also AI running. Every NPC near enough to be rendered has their own scripts going. For Call of Duty players, it's their allies and enemies navigating the terrain or shooting, or patrolling, for Skyrim, it's NPCs like J'zargo animating and testing to make sure you're not too far away from him. For 3D games, there's another layer: the renderer has to render the polygons visible to you. Every frame, all the visuals are rendered, and on modern games, that's quite a chore. This is why system requirements for some games can be astronomical.
So, naturally, in any given game there is a lot going on that you can't see. Now you understand why frame rates slow down. Let's try another experiment. If You have TES 4 or 5, load one up if you haven't already. If you're on the console, do the cheat that allows you to clone hundreds of items. If you're on the PC, open up the console and enter the command to spawn hundreds of an item in. Or if you'd rather not cheat or break the game, refer to this video. You'll notice the game starts slowing down the more items you spawn. The reason this happens is because of collisions. Each time an item comes in contact with another item, it has to handle the collision, as well as the collision with the ground, and the physics engine. That's on top of all of the stuff going on in the game already. The more items it has to calculate things for, the more work your computer has to do. In the video, at about the 50 second mark, you'll notice the background vanishes. This was a failsafe designed to reduce the stress caused by all the items appearing and all the calculating it has to perform. By reducing the draw distance, it's reducing the load on the game in an attempt to keep it running at a reasonable pace. Of course, it was never meant to handle all the items the player in the video is spawning, so it doesn't help a whole lot.
In this video, you'll notice the game completely hangs at first. This is because when the watermelons first spawn, let's say 200 of them, every watermelon's physics has to be calculated, plus the collisions between all 200 watermelons must be calculated. That means the game has to calculate 19,900 collisions. Spawning too many items for the game and your computer to handle will actually cause it to crash.
A good chunk of the time, too many scripts running at once is the cause of a lost in frame rate. Sometimes it's the fault of us, the developers, sometimes its the fault of you, the gamers. Go easy on us. A dip in the speed of the game can be as easy as "oops, I forgot to make sure this section of code doesn't run more than once." Like a part of a script I found in my game, while hunting for that bug.
And there's nothing we can do when it's your fault. If you have a million redstone repeaters in Minecraft, or spawn over a thousand lettuce in Oblivion, or mod a gun in Call of Duty to shoot some animated object that doesn't despawn, there's little we can do to keep the game running smoothly, and nothing at all we can do to keep the game from slowing down and crashing if you keep going. Short of giving you a hard limit on the amount of items you can spawn in a given area, there's no real way to stop you from wrecking your frame rate.
Anyway, that's probably about all I can teach you without getting into the technical aspects. There are a few other reasons frame rate can drop, but explaining those wouldn't be nearly as fun. I hope you learned something new about what goes on under the hood when you're playing a game.