• Advertisement
Sign in to follow this  

Where do you keep global variables?

This topic is 4141 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This might be a stupid question, but I still haven't come up with a good code design for a game. People tend to dislike global variables, but how should I organize my project? Things like the directx device, camera, player actor reference, camera location, frustum, resource manager etc will be used all over the project. I don't think keeping a reference to each of these things in every object is a good solution eighter. Should all of these things be passed as arguments? If I then add one more "global object", I will have to update hundreds of functio calls. Should I create singletons for each object? Or perhaps create an abstract kind of class named renderer, engine or something like that, make it a singletone and let it own all the managers and global objects such as camera, frustum etc. However do I really want to have the "renderer-like-class" to keep a reference to the player actor? Should there be some other singleton to keep more specific game related globals too? I'm confused. I can't come up with a good solution for this :(

Share this post


Link to post
Share on other sites
Advertisement
the camera, dx device frustrum etc will probably only be used by your renderer right ?
it might possibly be modified by some other part (game logic moving the camera) but that should be done using methods i guess.

i usually keep the player actor reference in the games main class along with all other actors though not always (depends abit on the game), in most cases i try to keep the player pretty generic so that the engine has support for multiple players or AI actors supporting the player, thus noone really needs to know about the player specifically, they just need to know where to look for other actors.

the renderer doesn't need actor information, it only needs to know about the graphical representation of the actors, the camera, the frustrum, etc.

Share this post


Link to post
Share on other sites
When people say "theres too many objects to pass everything as arguments", what they're really saying is "I'm too lazy". Of course when you get over that mental gap you'll be pleasantly surprised that the problem is not as huge as you think. Most objects are kept pretty local, often you only need a single class as some kind of high-level interface. And not every system needs to talk to every other system.

Share this post


Link to post
Share on other sites
Quote:
Original post by DanielH
I don't think keeping a reference to each of these things in every object is a good solution eighter. Should all of these things be passed as arguments? If I then add one more "global object", I will have to update hundreds of functio calls.


Your problem stems from bad design of your functions, and not from data lifetime and accessibility. When you write a function, you decide what it will do. Updating a function means adding arguments to it, which can only occur if your function's purpose was incorrectly described in the first place — because you decided to have it do more work than previously thought. This is usually a bad idea: write your functions once you know how you will use them (so you don't need to add new functionality) or write a new function to perform a new task, perhaps using the previous unmodified function to do part of that task. Changing the contract of a function, whether by adding more arguments or by having it access global variables, is an excellent way to introduce bugs. I would honestly rather have to run through all places where the function is called, reading and correcting them, than having the expectations of a hundred function calls grossly violated without checking because I used a global variable.

Another problem you have is the hiding of information. A renderer class should keep references to all actors, because its job is rendering all currently visible actors. That one of these actors is, in fact, a "Player Actor" holds no relevance at all to the renderer, because a renderer cares about "rendering", not about a "player". Introducing "player" information where it does not belong requires you to create more special-case code without any associated gains — even if a Player Actor global exists, it's simpler to just handle it as any other actor and have the renderer reference it anyway. Things like a frustum should never be visible outside the renderer, because they're irrelevant to non-rendering code. A camera is a rightful property of a renderer. A resource manager may be associated to a renderer (at which point it would be a member) or even owned by it (at which point it might be made completely invisible to the user).

You should try to create a game or program without using a single global variable: it's a very good learning exercise in software design, which forces you to actually tackle ownership and composition issues, instead of sweeping them away under the "it's global" rug and get bitten in the rear later on.

Share this post


Link to post
Share on other sites
The problem is that I need access to the frustum in for example my QuadTreeNode class and I have a class that is derived from a GameObject that render terrain patches. This class needs to know where the camera is to determine distance in the LoD calculations. So it's not as simple as just putting it all in the renderer class. So you mean I should pass all the needed arguments around? Like renderer, scene graph, frustum, camera etc to every update, render and device event functions? That would require insane amount of work and be really ugly! I'm coding in C# by the way. Would it really be such a bad idea to keep a totally static class with globals (renderer, camera, managers...)?

Share this post


Link to post
Share on other sites
A single game engine can be done as a single global (or singleton if you prefer).

I don't believe being a purist and not-making any[b/] globals is advantageous.
It becomes a chore having to pass the objects down the hierachy to the smallest object (for example if a GUI button required sound/input/graphics subsections of the engine).

One reason not to use globals is that tracking down bugs becomes harder.
This can be partly solved by making accessor classes that enumerate all the classes which access a certain section of the engine.

For example if I wanted to use the Input subsystem (mouse/keyboard) I would derive from InputListener class which would provide a method to access the Input sub-system of the global/singleton game engine. Whenever a InputListener is instanced in debug mode it could log its access (sufficiently advanced error logging helps).

Share this post


Link to post
Share on other sites
Quote:
Original post by stevenmarky
for example if a GUI button required sound/input/graphics subsections of the engine


*BUZZ!* Bad design, sir. A GUI button should only be responsible for its being pressed and unpressed. The owner of the button, though (which would have access to said subsections) can bind the button's onClick event to what the button is meant to do.

Share this post


Link to post
Share on other sites
Quote:
Original post by DanielH
The problem is that I need access to the frustum in for example my QuadTreeNode class and I have a class that is derived from a GameObject that render terrain patches. This class needs to know where the camera is to determine distance in the LoD calculations. So it's not as simple as just putting it all in the renderer class. So you mean I should pass all the needed arguments around? Like renderer, scene graph, frustum, camera etc to every update, render and device event functions? That would require insane amount of work and be really ugly! I'm coding in C# by the way.


So, rendering certain GameObjects requires access to the Camera class. Pass the camera to them in their constructor. That way, no unnecessary passing of cameras occurs at all once you start rendering, and the use of the camera by that kind of GameObject is made clear.

Quote:
Would it really be such a bad idea to keep a totally static class with globals (renderer, camera, managers...)?


Look at it this way: you decide to store a stick of dynamite next to a fireplace, and ask "Would lumber be a good replacement for the walls once they blow up?" Yes, lumber (global variables) are probably the best you can use in the situation where your walls have been blown up (very bad, vague and redundant design). However, not keeping a stick of dynamite next to the fireplace (using a correct design) would eliminate the need for rebuilding (global variables) altogether, in addition to making your life easier.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by stevenmarky
for example if a GUI button required sound/input/graphics subsections of the engine


*BUZZ!* Bad design, sir. A GUI button should only be responsible for its being pressed and unpressed. The owner of the button, though (which would have access to said subsections) can bind the button's onClick event to what the button is meant to do.


Sorry, I meant 'a particular class of GUI button' e.g. class PlayAnimalSound derives from class Button. I didn't mean my generic button class should be responsible for anything other that monitoring being pressed and unpressed (and perhaps being drawn).

Share this post


Link to post
Share on other sites

You should think really carefully the function of each class.

For example, I have a gfx class which does all the actual rendering (it is implemented through an abstract interface so that the program doesn't have to know anything about the rendering or the API).

For example, I keep my mesh data in a generic geometry class. When the mesh data is loaded, I give this geometry object to the gfx class and ask it to create a renderable object from the geometry. This way I am able to hide the implementation of the drawing from the program.

Try to avoid singletons. Even if it seems unlikely that you never need another instance of the object that day might come. Using singletons might lead to troublesome dependancies and the destruction of a singleton object isn't always clear. You can still have a class that contains the pointers to most of the interfaces in your program. Of course, at this point it is good to remember that all the objects shouldn't be able to do everything.

- So, try to make the classes in a way that they practically do only one thing.
- Share the duties, collision handling shouldn't be related to graphics.
- Keep thing clean, for example : no other class than the renderer should know about drawing details, locking buffers, etc.
- You might need several resource managers (renderer might need one for textures, meshes. sound system for audio samples etc).
- etc.

Cheers

Share this post


Link to post
Share on other sites
Quote:
Original post by stevenmarky
Sorry, I meant 'a particular class of GUI button' e.g. class PlayAnimalSound derives from class Button. I didn't mean my generic button class should be responsible for anything other that monitoring being pressed and unpressed (and perhaps being drawn).


I see, sorry for the misunderstanding.

Well, a PlayAnimalSound needs to know what sound to play, so you'll have to provide the object with that particular information when you create it. And, if your design is good, then the sound object can be played without requiring additional knowledge.

Share this post


Link to post
Share on other sites
To answer the original question: if something genuinely is needed all over the place then a global is fair enough – or, this being C#, a public static member of something. I prefer a Globals class as opposed to making singletons; as someone said above, you never know when you need two or more things, and it can be hard to re-engineer a class that only expects one instance of itself.

For a game, I'd tend to put 'global' things in the Engine class: one instance of the game engine requires one renderer, one sound manager etc. So they're not really global; if you had two game engines running at once you might well need more than one of each. But they are public and therefore visible all over the game.

But, and to reinforce what other people have said, generally globals are indicative of bad design – even 'pseudo-globals' like this. I would limit globally available things to the top level components at most, and perhaps even those shouldn't interact with each other but should have everything choreographed by the Engine class. But there are of course no hard and fast rules in design issues.

To just go through the things you mentioned:
Quote:
Things like the directx device, camera, player actor reference, camera location, frustum, resource manager etc will be used all over the project.

The DirectX device handle should be visible only to the renderer, so it should be a private field of it, not a global.
The camera location is a part of the camera object! The frustrum should as well, unless I misunderstand what you meant there (what the camera can see is a property of the camera).
The camera object is probably fair game for 'pseudo-global' nature, as the renderer needs to know about it (obviously), and it may be influenced by in-game events.
The 'player actor reference' should be visible to the input system, so it knows which entity to control, and to the HUD. These systems can just be given a reference to the right entity on level startup though.
The resource manager depends on your architecture, but it's likely that this should be a 'pseudo-global' (public within the engine) as various subsystems may want to use it.

Share this post


Link to post
Share on other sites
struct Scene
{
Camera camera;
..
..
};

extern Scene *g_SC;

u should have a couple of global variables (for code readibilty mainly)
eg for the above (which i use in my app)
thus whenever u wanna refer to something in the scene use g_SC->dothis(..);
singletons aint needed, make it a pointer thus u have control when the object is con/dis/tructed





Share this post


Link to post
Share on other sites
Well I agree with what a lot of people have said about designing your functions well in advance and avoiding globals. However when making a game sometimes the pure and correct design cannot always be achieved due to speed issues etc.

Passing variables down through functions is OK up to a point but when you get lots of them you are going to slow down your code. Also I have never been happy with functions that take a variable not to use but purely so they can pass it on to another function that needs it. That seems to break the interface to me. I know you may say that should never happen if you design correctly but in the real world it will happen.

I use Singletons, as far as I know they are not yet banned in the UK! , and while I understand the problems with them the reality is they do not cause me problems and they speed up my code and they simplify design issues. I use them carefully (I realise some people over use them) and make sure they only refer to a strict interface to a component (collection of classes) e.g. graphics, AI, UI, Physics, File System, Utilities etc. Due to the increasing campaign against them I have looked into alternatives like using a registry that is then passed through function calls. The registry allows a pointer to be added under a UID (or string) and then only accessed by those parts of the code that know about it (bit like COM). It works fine but I do not think it is much better than using Singletons.

I work very hard to structure my game into separate components that provide one interface to the rest of the code. This way the component can be reused in other projects and bugs can be tracked down to that component easily. In your case the directx device belongs in my graphics component along with a camera. However there is also a camera in my world component. The one in the graphics handles DirectX specific functionality and just takes a position and rotation etc. The one in the world is an entity that can be attached to a partition system and works irrespective of the graphics API being used.

Anyway best go - rambling a bit :)

Share this post


Link to post
Share on other sites
I keep everything OO unless I need to speed things up, then it's down to C/ASM. So, basically if anything needs to be global, it's in a singleton class...

That's just me. =\

Share this post


Link to post
Share on other sites
Anyone with a view to using Singletons should really read this first; Washu on singletons (start with part one; "Why are you infected with Singletonitis?")

Now, about "[singletons] simplify design issues", I'm not convinced, infact in reality you are just side stepping something. In a way it's like having an elephant in your living room; you can not talk about it, paper over it and walk around it but the damned thing is still there.

Anything else on singletons can be found in the Washu journal entry posted above.

With regards to 'speed' and 'passing everything down', I'm not buying it. For starters I don't recall seeing anyone here saying 'pass everything down', or if they are they are advocating it at setup/creation time, you can cache a local reference to things in your class.

The speed issue is, imo, null and void given todays CPU power. Once a upon a time, with slower CPUs, buses and cache, this might have been an issue, however if you've reached a point where parameter passing down a stack of function calls is an issue then you probably want to check your design. Your CPU useage is going to obey the 20/80 rule; 80% of the time is spent in 20% of the code, in short speed is a poor reason to start throwing globals around.

And don't fool yourself, an singleton is still a global, it's just one pretending to be "safe" and "OO"... in the end it'll cause you more pain than it's worth, were as if you had spent more time on your design you could have avoided the pain...

Share this post


Link to post
Share on other sites
I ramble on a little here
Even Washu seems to acknowledge singletons have their uses, so it's just about using them sensibly. If you use them wisely then you won't have problems.
Something that would amuse me is if someone made a program which could convert all singletons/globals to non-singletons/globals and show how small an issue it really is.

One thing I'm not sure of in Washu's post:

Quote:
So how can the programmer guarantee that multiple instances of the object won't be created?


Well depending on how you implement the singleton (private constructor) only one instance can be made (maybe I missed the point here?).

Another thing about Washu's post is that he says a logging system would be appropriate use of the singleton pattern. Why though? When do you draw the line between when it's ok to use globals/singletons and not?

a) When you use the object so many times all over the place it would be a pain to pass it around? (he seems to state you couldn't factor it out, but a few sentences above states that it could be implemented as a non-singleton).

b) When the object is significantly more complex? a logger writes output to somewhere. So does a graphics object, so why can't graphics be a global (like cout)?

There is no clear cut division of what is an appropriate global and what isn't.

Also an observation I have made is that all game engines I have looked at contain globals or singletons (I'm not saying none exist that don't use them, but has anyone seen any that don't?).

Also the fact Fruny uses them makes me want to use them more (Fruny fan!).

I like the way that local aggregate classes can access their parents private members in Java (I think this is correct in concept).

class A
{
int c;
class B
{
doSomething(){print c;}
}
}


[Edited by - stevenmarky on October 19, 2006 4:01:24 AM]

Share this post


Link to post
Share on other sites
I have read many posts attacking singletons and there is a lot of sense in them but I have also read a lot of people saying they use them when they have to. Most of these posts describe what is wrong with them but do not describe alternative solutions to the reality of games programming. I know from my own experience in the games industry that they are used succesfully and from my conversations with many game developers since I left I have found they still use them. So I still think if you are careful and you limit there use they can be a genuine solution to real world game programming problems.

Perhaps the bottom line is that C++ is bust and we need a better language to face the huge software engineering task that is games programming.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
i want to say i can understand every advantage/disadvantage of the presented techniques. and im also wondering what to use.

first approach: passing as a parameter.
consider this:
you have a debug-logging-class whatever.
you would like to use it in the renderer.
then, you make your damn cool texture-manager.
you have to add it there, too.
you have to add it everywhere, since every class can log errors/debug-messages.

globals and singletons.
an advantage of singletons is, that you can control in what order they are con/de-structed. but i think that doesn't matter here, since you can do this otherwise. for example in your overall "engine"-class.
globals have the advantage, that they are contructed at program-load time and destructed at program-exit. thats ok for me, too.
so i think, between globals and singletons there is no difference.

dll interface.
this is what i do at the moment, i thought i invented this...
but whatever, its not different from globals or singletons either.
these are just "outsourced" to another file.
an "advantage" is, that the sdk-user (or whoever) can add his own implementations.
...and he cannot see the crap i wrote ;-)

Share this post


Link to post
Share on other sites
Quote:
Original post by Trip99
I have read many posts attacking singletons and there is a lot of sense in them but I have also read a lot of people saying they use them when they have to. Most of these posts describe what is wrong with them but do not describe alternative solutions to the reality of games programming. I know from my own experience in the games industry that they are used succesfully and from my conversations with many game developers since I left I have found they still use them. So I still think if you are careful and you limit there use they can be a genuine solution to real world game programming problems.

Perhaps the bottom line is that C++ is bust and we need a better language to face the huge software engineering task that is games programming.


Just because something is widely used doesn't mean that it is used with success. Singletons share the same problems as global variables, plus some other because they need to be sure that only once instance is created. Most of the time they are used to answer the same exact problems than a global variable, making the "make sure there is only one global instance" thingy quite unuseful.
same
And to be fair, if you are able to successfully use singletons in a game project, then your project doesn't qualify as a huge software engineering task. Let me explain.

OO in Game Programming is not different from OO in other computer engineering fields (I have yet to see an argument that prove the contrary). The difference is more a lifetime difference than anything else (code is developped once, and most of the old code is discarded when a new game is to be done - this is short development cycle (2 or 3 years), while most software projects have a development cycle of 5 years or more (15+ years)). Moreover, the team that develop the game is often quite small (10 to 20 programmers is already a big team in the game development industry). The team is often made of core members that were here at the beginning and that are still here at the end. This short lifetime + the way team works makes the code maintance a less important problem, since a new code base is supposed to come right after. This is also a reason why teams now have to rely on middleware: code bases do not evolve well, thus any major publication needs to use a new code base. To reduce the cost, they use a middleware that they don't have to maintain.

Of course, it would be enterily different if the industry decided to use correct methodologies and OOD practices to build their game. The middleware market would be less important but the games would not take longer to be completed. This would also lead to more maintanable code.

Singletons are a real threat to maintenance - as well as global variables. You are not able to be sure that the singleton's invariant is correct in all situations, unless your singleton is stateless (in which case a bunch of global function is enough). Moreover, they tend to spread and to infect the code base, meaning that simple refactoring operations become more and more difficult as long as the project get older. The code base begin to rot, you begin to add more and more stuff in the singleton classes because it costs less than doing the same thing in the correct way and you're doomed. Your next game now have to use another, more viable code base - so you'll use a middleware, or you'll start from scratch.

Successful use of the singleton pattern is something I haven't seen in my life yet.

Regards,

Share this post


Link to post
Share on other sites
Quote:
Successful use of the singleton pattern is something I haven't seen in my life yet.
(!)

:shrug: I've seen plenty of singletons and globals used succesfully.
We must have a different definitions of success. My definition is the same as the dictionary one :)

One example is Ogre3D.

Share this post


Link to post
Share on other sites
Quote:
Original post by stevenmarky
Quote:
Successful use of the singleton pattern is something I haven't seen in my life yet.
(!)

:shrug: I've seen plenty of singletons and globals used succesfully.
We must have a different definitions of success. My definition is the same as the dictionary one :)

One example is Ogre3D.


Did I make you shrug! [smile]

Ogre3D is a complete failure from a design point of view. Its singleton are not even enforced at compile time, making them rather poinless. You can destroy them at anytime you want, and recreate them right after, making them even more dangerous than any other working singletons I've seen before.

We may have a different definition of success, but I suspect it is not the case. My statement comes from my own experience, both as a professional software architect and developper (I still occasionally dive into code, but it tends to be less and less frequent - although it is the case atm). Your mileage may vary [smile].

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I wouldnt say you want to use exactly singletons. In fact u use globals wrapped in a class :)

And I think is it ok, but u must be very careful which objects are good candidates.

example of good candidates:
- renderer
- sound engine
- input
- various resource managers(but be carefull what you really need here)

these objects are mostly singletons as you usually dont need two renderers/sound engine/... in your game. You will find your code MUCH easier to read, maintain a get a nice speed bonus as opposed to passing references whenever you need one of these. My experience comes from a very large game project(10+ programmers) and we just didnt find any better solution - in fact trying to do everything too OOish was contraproductive. Keep OO abstraction at the lowest reasonable level (where you want to reuse code or detect need to refactor code later). But dont be mistaken - it still requires the same ammount of thought and design as purely OO thinking!

bad candidates:
- camera/frustum/camera location: what about mirrors, reflections or security camera screen in your game? :) These are prime candidates for multiple objects in your game (unless you do something really simple)
- player actor (ask game object for this)
- dx device - hidden in a renderer and should not be accesible at all

MaR

Share this post


Link to post
Share on other sites
Quote:
Ogre3D is a complete failure from a design point of view. Its singleton are not even enforced at compile time, making them rather poinless. You can destroy them at anytime you want,

You could destroy any object anytime you want as long as you are in the relevant scope.

I admit that not using singletons could make this easier to track, but sensible people wouldn't randomly destroy objects anyway.

My mileage probably does vary, I am a professional software engineer though.

Share this post


Link to post
Share on other sites
Quote:
Original post by stevenmarky
I admit that not using singletons could make this easier to track, but sensible people wouldn't randomly destroy objects anyway.

But the whole point of singletons is about protection - it can happen that code is used by people who are not sensible enough to understand it [smile]. Ogre's singleton doesn't present any kind of robust mechanism to avoid this. As a consequence, their singletons are worthless - and since you can destroy them at anytime, this also indicates a bad representation of the global context (a global variable that can be destroyed at any time makes a very poor global variable, as you can't even control if it is global enough. Globals should be here at the start of the program and should go out of scope with the program end. This excludes anything that can be dynamically created or destroyed).

I made the comment about my professional experience to back up what I said. It doesn't not imply that I'm good at software engineering - it says only that while working on these subjects, I haven't seen any successful use of this pattern :)

Regards,

Are we derailing the thread to a singleton flamewar? I hope not!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement