My column this week answers the question posed by the title, which means the Title Police can piss off and can’t refer to it as “clickbait”. (Seriously, the Title Police have become almost as annoying as the clickbaiters by this point. But that’s a topic for another day.)
This is yet another topic where you can go an inch deep or a mile deep, and you still won’t hit the bottom. It all depends on how much technical knowledge you demand of your audience. On the Escapist, I tried to keep things broad and accessible for general audiences.
But let’s look a little deeper:
In C-flavored programming, we have pointers. You ask the operating system for a big ol’ wad of memory, and you use that memory to store some crap. Maybe it’s the 3D model of the space marine. Maybe it’s the texture map of his face. Maybe it’s the animation that makes him look angry and constipated when you’re holding down the fire button. Maybe it’s the grunting sound he makes when the player jumps. Whatever. You get some memory and you put stuff in it.
A pointer is just an address of memory: “The space marine face is stored at memory location #1,234,567.” The most expedient way to code is simply to create the object, and then let other systems grab that pointer whenever they need it. To save time, those other systems might save the pointer so they don’t have to keep looking it up.
So far, so good.
But then we change some graphics settings. Maybe the user bumps the texture resolution from “low” to “medium”. Now we need bigger textures. But all the textures we have in memory are for “low” texture mode. So we release the memory for the space marine texture at #1,234,567 and get a new block of memory to hold the bigger texture. This new texture will probably live at a new address. Say, #2,345,678.
Now here is where our programmer starts to worry. How many other systems out there have the old address? What if one of them tries to use it? If they do, they will very likely crash the game. How can we keep this from happening? Various people will offer suggestions:
You can tell everything to always ask for the latest address of everything, always. But that creates a performance overhead. If this thing is something you use ten thousand times a frame, then any performance cost on that object will end up multiplied by ten thousand. This is really important these days when developers seem to be just barely able to maintain 60fps, and they need to save all the CPU cycles they can.
You can tell everything to update itself one a frame. Once at the start of a frame, everything can re-query all the addresses. But this creates a great deal of uncertainty, particularly when dealing with complex systems. Maybe when I’m updating a character, it has the check on the address of the model, and in the process of doing that, the model ends up (for some reason) trying to use (or even just examine) the texture. You end up with this chain of things that need to be checked in just the right order and the programmer has to understand how every single object interacts with every other object.
You can run around updating everything right at the moment it gets changed. So the user changes the texture settings and the game immediately stops everything and forces every object to update just to make sure all the pointers are current. This pushes the problems into the future. Later on, a new programmer joins the team and nobody has explained to her that when you add a new thing, you also need to add that thing to this global refresh. She’ll run around adding all sorts of useful features to the code without noticing anything is wrong. Then a playtester tries to change the graphics settings and the program dies a horrible death. Now we have to go back over the last few weeks of work and find all the things she added and “fix” them. It creates folk knowledge that you “just have to know” in order to work on this game. It doesn’t sound too bad in this example, but when you have thousands of systems that all have these little “by the way, make sure to always do X” things, it becomes dauntingly complex to keep track of them all.
And none of these techniques will help if your game is multi-threaded. Let’s say you’ve got this bit of code:
1 2 3 4
//Let's make sure the pointer is up-to-date! pointer = GetNewPointerLocation (); //Okay, that's safe now. We can proceed: DoSomethingUseful (pointer);
What if some background thread happens to change the location of that thing just after line #2 but before line #4? That’s a ticket to crash city.
People usually try to fix this with programming orthodoxy: Never use simple pointers! Always use classes with constructors / destructors! Comment your code! Use this strict programming paradigm! Those solutions might help mitigate the problem that your code is now ten times as complex, but none of them as as easy, as safe, as clear, and as future-proof as simply wiping the slate clean with a restart.
And that’s why game development sucks and only a fool would try to make a game in this day and age.
Tomorrow! An update on the development of my indie game Good Robot!
Was it a Hack?
A big chunk of the internet went down in October of 2016. What happened? Was it a hack?
The Best of 2013
My picks for what was important, awesome, or worth talking about in 2013.
A programming project where I set out to make a Minecraft-style world so I can experiment with Octree data.
The Mistakes DOOM Didn't Make
How did this game avoid all the usual stupidity that ruins remakes of classic titles?
What is Vulkan?
There's a new graphics API in town. What does that mean, and why do we need it?