Ways to avoid the needs and the musts of global variables??

Started by
86 comments, last by swiftcoder 13 years, 3 months ago
The times I feel like i need global variables is:
When I have a lot of variables that everyone needs to know.
When I reach this point I usually pass a "Parameters" object to all of my objects.
This Params object contains all of my large scope data.

Beware of singletons! They are just as bad as global variables! You will encounter most of the tedious problems that come with global variables if you use them. Maybe except for name-space problems.

For me, the only acceptable time to use global data:
1) It is a constant read-only value.
or
2) It is a machine-wide or OS-wide value/function.

My Oculus Rift Game: RaiderV

My Android VR games: Time-Rider& Dozer Driver

My browser game: Vitrage - A game of stained glass

My android games : Enemies of the Crown & Killer Bees

Advertisement
just put the stuff there where you need it, and pass it around to those functions that use it.

that's just the way it is.

in case of a logger, in c++, i would only have some log() function, no actual class anyways. but even if i would use a class, i would instantiate it where needed, and immediately kill it again. or pass it around as needed.

so the answer is: just don't. then you see where you need your stuff, and put it there.
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

@SillyCow: Dont worry, Im using "managed" singleton, as in enginuity articles
@DavePermen: Now I know, that engine data should be exposed (accessible) to the game but not vice versa. That means I can safely store game vars in its own class, which is what Im doing now :D
If it were me I would use global variables in your project if it makes you more productive. For too many years now have I wasted time trying to architect a game or engine properly and not just got on with being productive. Using globals for all managers, or for the logger in your case is way WAY more productive than fannying around with making sure everything is passed to everything correctly. People have this "fear" that using globals is bad because it means the data is unsecured. Its not insecure if you're the only one coding on it.

If you're writing a project in a business environment or writing some kind of SDK for others to use then sure, do it "correctly", but just get on with making your game for now :).

Dave
Quote:Original post by Bow_vernon
How do you do it? right now Im making a App class and put all program variables there.


I use a similar approach. Sometimes its just completely impractical to use anything other than a global/singleton (passing an object round and round and round is just...). I saw a nice approach in Game Programming Complete that I have adopted. It goes something like this (may not complie, its just to give you the idea):

class A;static A* instance = NULL;class A{    A(bool global = false)    {        // Maybe there should be a check to make sure this isn't overridden        // but I kinda like the fact that you can swap out the global        // for a different one "start using remote logger object"        if(global)            instance = this;    }    ~A()    {        if(this == instance)        {            instance = NULL;        }    }    static A* Instance() // could return a ref (and use assert)    {        //Some checks, maybe an assert        return instance;    }    };


The idea is to make it globally accessable but without the trouble a singleton brings. You create it in a high level object before its going to be used by anything. In my game I have a global lua object (but then I can still have local ones when needs be) I then have things that require that lua object such as the ui. I can then create the lua object, create a ui object and pass it the lua object (I try to pass things even if they can be accessed globally). On clear up I can delete things in reverse order (ui then lua state, something that would cause random problems if using true singletons.

I find this approach really neat, as long as you delete objects in the reverse order from how you created them they clean up really well which was a big problem when I used static singletons. From the word go there is a single entry point object which has subobjects and so on. Theres then never any problems with an object not being ready for use or being deleted but needed later.

Stick to your "globals" being owned by something, I think thats a great idea.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Quote:Original post by Bow_vernon
@SillyCow: Dont worry, Im using "managed" singleton, as in enginuity articles
@DavePermen: Now I know, that engine data should be exposed (accessible) to the game but not vice versa. That means I can safely store game vars in its own class, which is what Im doing now :D


so you're still using singletons. replace them with globals to at least show what they really are.

and then remove them :)
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

Quote:Original post by Dave
If it were me I would use global variables in your project if it makes you more productive. For too many years now have I wasted time trying to architect a game or engine properly and not just got on with being productive. Using globals for all managers, or for the logger in your case is way WAY more productive than fannying around with making sure everything is passed to everything correctly. People have this "fear" that using globals is bad because it means the data is unsecured. Its not insecure if you're the only one coding on it.

If you're writing a project in a business environment or writing some kind of SDK for others to use then sure, do it "correctly", but just get on with making your game for now :).

Dave


QFT.

I have an Engine class which is a container for all of the main high level systems and have a global instance of it. People say that you should be reducing coupling and whatnot, but I don't really see that making much sense in a game. A lot of the components tend to work with each other, and being able to swap out components half way through development isn't really something that will happen if your code is well planned out. Even changing SDKs/APIs for something like physics, sound or input (or even rendering) shouldn't be much of an issue anyway as different APIs all try and achieve a similar result, and thus can use similar interfaces.

So I guess, put more emphasis on the high level design of your code rather than trying to architect the perfect OOP solution with 0 globals where references to all your managers are passed around as required, because it will get out of hand pretty quickly if you aren't careful.
[size="1"]
a simple example: a graphics engine singleton. as one never needs more than one.

all the stuff wrapped in there, all working great. then, one day, you have the idea of copying your code to create an editor with engine-graphics. as it makes sense, the editor gets top, side, front and perspective view. to handle those (and let artists chose), you create multiple window-controls, and want to render into each.

and suddenly you need more than one, because you need an instance per window-control. if you would have made the graphics engine instance part of the singleton, as you should have in the first place (because it is an item of the actual window-control), this would have been a NONISSUE. now you have to rework it so it works with multiple instances.

you never know the future. so better don't code in a way that might get in your way later on.

if you just need one of something, just CREATE one of something. if you want it to be global, do it globally. but forget about singletons instantly, they provide NO gain at all. NONE. and if you get rid of globals on the way, even better. it really isn't more hard to code without singletons. it can be hard, though, to refactor some code to get rid of them, once they are a problem.
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

Quote:Original post by davepermen
<snip>




I agree with this. An example I have on this note, also related to the editor. Like I said above I have the engine global which contains a World object (class which allows loading levels etc). However my editor is integrated to the engine. I wanted to have a "play in editor" function, so I ended up giving the editor its own World, and when entering play in editor mode, saving the map off and loading it inside the main Engine world.

Ended up being really easy to implement a very useful feature. (Some might argue that this is a less memory efficient way to do this or whatever... but that's beside the point that I'm trying to make :P).
[size="1"]
Okay, Okay enough. Singleton is bad. Good news : I only use it for Logger and Kernel class (I really only need one and global access by other engine components). For other subsystem(Graphic, Audio, Input) I dont 'singletonize' them for the reason you EXACTLY mentioned above. O please dont kill me :p

This topic is closed to new replies.

Advertisement