Globals

Started by
12 comments, last by Stainless 10 years ago

Recently a nice article showed up, http://www.gamedev.net/page/resources/_/technical/game-programming/a-long-awaited-check-of-unreal-engine-4-r3635 where there are parts of Unreal Engine revealed. And what got my attention was this line in one of the listings:

ENGINE_API UEngine* GEngine = NULL;

It looks like even best of the bests use globals... :)

Advertisement
Note some details about that global.

First off, the global is invariant. No system within the game modifies it. This avoids the largest collections of issues with global variables. You don't worry about multithreading concerns and race conditions with the value changing, or the value changing mid-use, or locking semantics, or a large number of bugs.

Second, the primary purpose is to serve as a service locator style object. You can use GEngine to find the other components and systems. It becomes a well-known instance, rather than a singleton.

Third (and flowing from the earlier two) the global is not shared state. It does not represent a value or collection of values that many systems used in a free-for-all. The object allows access to subsystems through access control and uses constraint checking, and does so on a well-established term.

Fourth, this is a global pointer, not what most people consider a global object. When most people think of "global" they think of an instance that is initialized statically (before main is called) and cleaned up sometime after main exits. This is a pointer to an object with a well-established lifetime. In that respect it is not what most people think of as a global.

As such it avoids most (but not all) of the problems associated with global objects.


That being said, it still does cause some issues. Systems rely on that value to be set externally and for it to be valid. This can make automated systems like tests harder to implement and maintain. Systems that rely on it have some added coupling that they otherwise might not desire. At a lower level individual components do not need to rely on the object, they can be written in an agnostic way that takes a pointer to a system, with the caller providing GEngine->getWhatever() to provide the specific instance to operate on.

So it is a less-bad situation than it might first appear. It does introduce some avoidable coupling, but the engine designers have minimized the overall problems, and are willing to live with the remaining consequences to take advantage of some convenience it offers.
I haven't used Unreal since 2.5, but their code used to be "typical C++ bullshit", incorrect-OO everywhere bad code ;P

Just because a building is popular, or had a lot of tenants, it doesn't mean that the foundations are sound or that renovations would be easy ;)

Globals are like any other construct that exists in programming. Used well, they are excellent. Used badly, they are the spawn of satan.

I worked for a large company that refused to let developers use global variables, at the time we had 256K of rom for the entire code and 512K of ram.

We would develop a product, ship it, archive the source code, then start on the next product.

Just before shiping we would always have the problem that we were a few K over budget on the rom and there would be a mad panic to optimise everything.

Once I added a single global variable and saved 20K of rom.

For me it's not an issue of should I use globals or not, I will if I need to. It's more a case of do you know enough about the system to know when using a global is safe and an improvement.

This topic is closed to new replies.

Advertisement