Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Is it practical to have two instance of a Game class object


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 warnexus   Prime Members   -  Reputation: 1535

Like
0Likes
Like

Posted 29 January 2014 - 10:30 PM

In my game, my Game class is not a singleton class so it is possible to have more than one instance of Game class running. But I have no idea if in other games where there is a reason to have more than one instance of a Game class object running. 



Sponsor:

#2 Dave Hunt   Crossbones+   -  Reputation: 3533

Like
7Likes
Like

Posted 29 January 2014 - 10:34 PM

If you don't want more than one instance of your Game class, then don't create more than one. There is no need to make it a singleton.

 

Whether it's practical to have more than one Game object instance or not would depend on its implementation, but it's unlikely to be a useful feature.



#3 Squared'D   Members   -  Reputation: 2337

Like
2Likes
Like

Posted 29 January 2014 - 10:50 PM

Yeah. Like Dave Hunt said, if you only need one, just make one. Sometimes is not good to over think things. Singletons add more unnessary complexity that goes beyond just saying there can only be one. You'll also be giving global access to the object which can cause problems down the line as ownership and the interactions won't be clear.

There may be a reason to run 2 instances at once if the app wants to run 2 simultaneous simulations, but it depends on the needs of the needs of the app.

Learn all about my current projects and watch some of the game development videos that I've made.

Squared Programming Home

New Personal Journal

 


#4 LorenzoGatti   Crossbones+   -  Reputation: 3153

Like
1Likes
Like

Posted 30 January 2014 - 03:13 AM

Plausible use cases:

  • A "main" Game in an idle/paused state and an unrelated AI-only Game used as an "attract mode" demonstration or as a screen saver.
  • Multithreaded simulations of many running Games sharing read-only data, for example to validate levels or train AI players.

Omae Wa Mou Shindeiru


#5 samoth   Crossbones+   -  Reputation: 5877

Like
1Likes
Like

Posted 30 January 2014 - 04:29 AM

Another use case one could imagine would be split-screen games for two players. In that case, each "game" object would refer to the complete game experience for one player (not "the game") as such. In one-player mode, you'd put one game object into the "container" object, in two-player mode, you'd have two.

 

As for singletons, although most of their problems can be worked around, I'm with Dave Hunt. Creating exactly one of something if you want exactly one is simple and straightforward, so why waste your time implementing something complicated for the same effect. Singletons are easy to implement and use, and easy to implement and use wrong (though at least one annoying threading issue is solved by C++11 -- albeit I think the wrong way around: rather than making initialization thread-safe one should simply spawn additional threads later, which avoids the initialization problem in the first place).

Either way, there are cases where singletons are truly useful, but they're few. In most cases, you can do without them, and easier.


Edited by samoth, 30 January 2014 - 04:32 AM.


#6 Álvaro   Crossbones+   -  Reputation: 16172

Like
4Likes
Like

Posted 30 January 2014 - 04:37 AM

You might want to have two Game objects with slightly different configurations so you can test that their states don't diverge. Or you might end up writing a server for your game that can keep track of several Games at the same time.

Even if you can't think of a scenario where you might want more than one Game instance, keep the possibility open.

#7 jbadams   Senior Staff   -  Reputation: 23064

Like
1Likes
Like

Posted 30 January 2014 - 04:50 AM


Even if you can't think of a scenario where you might want more than one Game instance, keep the possibility open.

This!  Don't prevent yourself from making additional instances because you can't currently think of reasons you might need them; prevent yourself from making additional instances if you think of reasons it would be bad to do so.  By not imposing an unnecessary restriction on your code now you allow yourself greater flexibility if you find the need for an additional instance in the future.

 

A singleton is appropriate if it would be an error for more than one instance to exist and you need global access.  If you only need one of those or if they aren't strict requirements there's probably a less restrictive solution than a singleton.  smile.png



#8 Juliean   GDNet+   -  Reputation: 3712

Like
0Likes
Like

Posted 30 January 2014 - 07:04 AM


if it would be an error for more than one instance to exist and you need global access

 

In my personal opinion, those two prerequisites rarely ever occur, and even less likely together. First of all, when would it ever really be an error if two class instances exist? As already stated before often programmers mistake "I don't need two instances" with "there absolutely should never be more than one instance", and other than that, I can't see any reason why creating two instances of any class in a game could be harmfull. If one puts at least a little thought into his class design, this would never ever be the case, because each class would probably be designed so that it takes an input (in the constructor and in its output) and generates a meaningful output (via different methods), while maintaining a certain encapsulated state. So unless you are clustering your classes with the usage of global state, then it really should not matter whether zero, one, or 200 instances of any given class exists.

 

Also, regarding the global state, when do you really need global state? Most programmers, for example recently in my university, use global state (i.e. singleton) just to spare them the "overhead" of passing some classes down other classes constructors (Dependency injection). There is no real need for it to be global - it was used for convenience of writing less code, just as it might seem to be convenient to use little but huge classes, make a lot of state public, and so on... yeah, you should keep your programs simple and don't overcomplicate your program (K.I.S.S), but global state rarely helps that, and more likely produces a cluttered mess where all the sudden a lot of classes need to be singletons, because they depend on one or more other singletons and can therefore not be used in isolation with more than one instances (so in a way, using singletons can cause the need to use more singletons, if that makes any sense).

 

I felt to give my two cents because as I said I just recently experienced how singleton was misused by almost all my collegues in their projects, creating just what the OP asked for - a "game" class singleton that was used all over the project, being an unawful god-class to add in some cases too. I'm really annoyed that singleton is being taught with so little caution and still praised as being a good (if not the most useful) pattern, IMHO it should be taught as a anti-pattern, which it is in my opinion. There are one or two uses (thread pool, logger), buts you could also use a static class or free functions for that.

 

So, for the OP, no, don't make it a singleton under any circumstance, keep yourself open for the possibility to create more than one instance, and certainly don't make your "game" class globally accesible. Use dependency injection to hand it around the classes that need it, or even better, have it manage some sub-systems that you pass around instead of making it an almight god-class.


Edited by Juliean, 30 January 2014 - 07:05 AM.


#9 samoth   Crossbones+   -  Reputation: 5877

Like
0Likes
Like

Posted 30 January 2014 - 07:25 AM

mistake "I don't need two instances" with "there absolutely should never be more than one instance"

But that is the exact difference between a singleton and a single instance. A singleton must not, cannot exist with two instances. It's the reason why proper applications of singleton are so rare, too. Usually it doesn't hurt.

 

I can't see any reason why creating two instances of any class in a game could be harmful

Example:

class savegame_manager // loads last game session and saves it at program exit
{
	int fd;
	// ...
public:

	savegame_manager() : fd(open("blah"...)) { while(...) { read(...); set_gamestate(...); } }
	~savegame_manager() { ftruncate(fd, 0); for(...) write(...); }
};

Create two instances of these, and the second will overwrite the first one's save in its destructor. Or rather, since order of destruction is the inverse order of creation, the first will overwrite the second. See how I already got things wrong once in only two lines of text.

Or, if they run on different threads, something else will happen, likely corruption. If only the complete file is written twice, this is relatively "harmless" (assuming no exceptional condition happens in between), but it is nevertheless an error.

The example works with anything that opens files, creates render contexts, owns some resource, and so on. This very design (only with a different class name) has once upon a time been a source of many WTFs on a well-known open-source IDE where under some obscure conditions, the complete configuration would get lost. Which was of course totally impossible, but it still happened.

 

Create two objects that own the same handle and close it in the destructors. That'll generate an exception if a debugger is attached (it's harmless otherwise, but that is coincidence, try the same with calling free twice on the same memory address). Or create two objects that own/manage/modify the same whatever without anyone being aware of it (and thus without proper synchronization).

Recipe for desaster. And what's worst, it doesn't just go wrong -- it evidently goes wrong when actually it can't go wrong at all.


Edited by samoth, 30 January 2014 - 07:27 AM.


#10 Juliean   GDNet+   -  Reputation: 3712

Like
0Likes
Like

Posted 30 January 2014 - 07:35 AM


Create two objects that own the same handle and close it in the destructors. That'll generate an exception if a debugger is attached (it's harmless otherwise, but that is coincidence, try the same with calling free twice on the same memory address). Or create two objects that own/manage/modify the same whatever without anyone being aware of it (and thus without proper synchronization).

Recipe for desaster. And what's worst, it doesn't just go wrong -- it evidently goes wrong when actually it can't go wrong at all.

 

I see where you are going for, but thats kind of what I was talking about. In your example, I'd have it like this:

class savegame_manager // loads last game session and saves it at program exit
{
    int fd;
    // ...
public:

    savegame_manager(const std::wstring& stFilename) : fd(open(stFilename.c_str(), ...)) { while(...) { read(...); set_gamestate(...); } }
    ~savegame_manager() { ftruncate(fd, 0); for(...) write(...); }
};

That way, you can specify which file to load, and having more than one instance is now not necessarly harmful, unless you specify the same file two times, but that was your fault as the user. You could have a private static map to check whether a file is already loaded, e.g. As I said, a logger with a certain hard-coded file handle can be useful, but for a savegame-manager as in your example, its much more practical IMHO to being able to specify which file to use, which pretty much nullifies the necessity of a singleton. I get what you are saying though, but I hope you also see where I'm getting at it, there is probably always a better option than having a singleton.



#11 warnexus   Prime Members   -  Reputation: 1535

Like
0Likes
Like

Posted 30 January 2014 - 05:57 PM

Wow! A lot of response! I did not expect this. Okay I will keep my Game class open as not a singleton. Thanks for the practical scenarios on two instances of the Game class object.



#12 Hodgman   Moderators   -  Reputation: 40169

Like
4Likes
Like

Posted 30 January 2014 - 07:03 PM

Even if you can't think of a scenario where you might want more than one Game instance, keep the possibility open.

This!  Don't prevent yourself from making additional instances because you can't currently think of reasons you might need them.  By not imposing an unnecessary restriction on your code now you allow yourself greater flexibility if you find the need for an additional instance in the future.

This! biggrin.png

 

Another example -- to diagnose problems with networking, I have seen a games company simply instance two copies of the entire game-client within the one application, and hook them up via the networking system. They even plugged both instances of the game into the one scene renderer (tinting the objects from one of the clients a different colour). This let them visualize the state of a two-player network game using only a single PC, and whenever a desync bug occurred, it was immediately obvious (as a player/game-object would 'split' into two different locations on the screen).

 

The game wasn't initially designed to be used this way, but because it was written using clean and sensible software engineering practices, it was very easy for them to implement this "multiplayer testing" feature later on.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS