I’m still fairly new with Unity, so I picked up my habits from tutorials and guides. One habit I have which I’m starting to worry is bad is that I attach a lot of Managers to my Singleton Game Manager. And I know some people hate singletons but I don’t see an issue with it as long as its something only instantiated once at the start of the game, like a Game Manager.
But as my game grows, I find my self adding more and more to it (I.e more scripts), ofc only things that are instantiated once such as: Quest Manager, Inventory Manager, Dialog Manager, Event Manager, Data Manager, etc.
And implementation of this looks like:
if (npcObject.hasShop)
{
GameManager.instance.GetComponent<ShopManager>().CreateShopWindow();
GameManager.instance.GetComponent<ShopManager>().PopulateGrid(shopItemsData);
GameManager.instance.GetComponent<InventoryManager>().OpenInventory(false);
}
If this is not how you are supposed to do it, why not? and what should I be doing instead?
The main argument with singletons is that they aren’t really object oriented. They cause people to use globals. The problem is, games don’t quite have the same requirements, the main one being we need some objects to live across scenes, and we need to save certain information. The real question is, do these scripts need to cross scenes. If they do, it’s probably better to have them all in one place.
Technically GetComponent takes longer to execute the more components you have attached to an object, but 1) just doing it occasionally doesn’t make any measurable difference and 2) if you cache the GetComponent calls it’s a moot point.
Would like my code to be consistent. Cant decide if I should use ‘instance’ in every singleton with the same implementation I posted in my original question, or call them with GetComponent<>
They’re easier to find if you put each “manager” on it’s own gameObject. Then you can give each GO a nice name (especially since the “new” Unity lets you arrange gameObjects in any order. At first they were always alphabetically sorted.)
I’ve found if I stack several managers on one GO, it’s a pain scrolling to the script I want, and I sometimes confuse them.
This. Also true if you intend to plumb any other references into your singleton (such as assets)… nice if it’s all separated out visually. And sometimes you might find it handy to put custom editors on your game managers, and that gives each one its own inspector context.
Also, if you hang all your managers on one hairy game manager style GameObject, it’s harder to pluck one of them out and use it in your next game.
I think maybe it depends on how OO you tend to be. My managers tend to share information from each other, so, if I grab the one, I don’t have to worry about dependencies. If I want to do a test, I can just grab the one manager and I have all of them, which generally isn’t all that many anyway. Also, I have one object that needs to be destroyed if there is a duplicate. There might be certain things I would want separate, but in general, one just seems a lot easier to deal with for me. None of the “many managers” arguments work for me personally. I suspect it might have to do with game size. So far, I’ve only written small games.
Definitely a lot of truth in this. The interesting questions and views above really come into play “at scale,” and for various people that means various things. Someone writing a Flappy Bird clone isn’t going to operate at the same scale as someone writing a World Of Warcraft clone, but the points that drive scale decisions can teach us all a lot regardless of what scale we operate at. Unity3D is a great place to learn this stuff and try stuff out at varying scales to see what works!
If you want to have the same properties etc, you could write a generic singleton base class that provides that. That’s by far more consistent and less redundant.
Anyway, while you’re asking that question, it’s worth noting that the first way of access seems not as comfortable first, but you could actually avoid all other “obvious” singleton-implementations using the first way of getting the references.
You’d just ask for an instance and the game manager could be the one looking it up and / or creating a new one if one doesn’t exist.
Of course, you most-likely still want to make sure there will be only that one instance and others will be destroyed, but that can now be kept an implementation detail without letting anyone know about that, i.e. there’s no direct call such as SomeManager.instance.
Going a step further, I’d also add an interface (or if necessary, an abstract base behaviour). This allows to decouple the actual implementation from its interface. It’s a lot easier to throw in a different implementation later, since you’re not longer bound to a specific implementation (i.e. its class type).
Perhaps that’s not gonna happen in most cases, or never at all… But at least you’re prepared for that.
The actual problem with too many “real” singletons (or statics in general) is that your code needs to refer to a specific type in order to access something, like above, e.g. SomeManager.Instance. And that can turn out to be a huge mess at a later point, and it’s usually not that great from the perspective of software qualities.