Search Unity

Best "Game Management" approach.

Discussion in 'Game Design' started by Abdou23, Feb 12, 2016.

  1. Abdou23

    Abdou23

    Joined:
    May 2, 2014
    Posts:
    77
    I'm working on my very first unity project here, a 2D game for mobile devices. I read a lot about singletons and the idea of "Game Controller" to manage the game, but what I noticed is that that game controller always handles the general aspects of the game, for example: (score, unlockables, load scene) but how about managing the game logic itself? for example: (if enemy1 dies then spawn enemy2, if score>50 then speed++) Should I put that game logic inside the game controller or is it better to separate it into a normal prefab that holds it's own values in each level?

    Also, if I went with the game controller and level manager approach I will still be left with in-betweens logic, for example: (Pause screen, music, show ads)

    What is the best common approach for stuff like this?

    Thanks in advance for your help.
     
    Last edited: Feb 12, 2016
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    If it's level-dependant, I recommend using GameObject that's in that level (like a Prefab way you described for example). Singletones are good for things that don't change between levels or code that doesn't really belong to any class. If you would make singletones keep level-dependant data and change levels, you would still need to 'load' their values from level and that's just additional hustle.

    Also if you're making singletones, say Unity hot reload goodbye unless you want to dive deep into serialization.
     
  3. aer0ace

    aer0ace

    Joined:
    May 11, 2012
    Posts:
    1,513
    There's no immediately correct answer. But I can tell you what I'd do.
    I'd have an EnemyManager to handle this example. EnemyManager can potentially be accessed as a singleton, or as part of a system owned by a GameController object, which in itself would either be a singleton, or a script attached to a game object for the Start() and Update() hooks for your main game loop. You could even have both, but that's risky and probably not recommended for large teams, as communicating this can be confusing.
    I have a messaging system as well. Monobehaviours register as message listeners, and I have a Message pump. I'd have a EnemyDeathMessage that gets sent to the message system, and all monobehaviours that have registered the EnemyDeathMessage, i.e. EnemyManager, can do something else, like spawn enemy2.

    I'd have a separate ScoreManager, probably a singleton as well, or as before, a system that's accessed from the GameController. This is where you set and get your score for testing. If you really want to destroy dependency on ScoreManager in your classes, you can also add ScoreMessages to your message pump, and have ScoreManager receive these messages to set them.

    EDIT:
    What I mean by destroy dependencies is that you want to decouple your systems as much as possible. The message system does this as long as you have generic data types stored in your messages, and translated back (unpacked) to game objects with properties that make sense for the receiving system.
     
  4. Abdou23

    Abdou23

    Joined:
    May 2, 2014
    Posts:
    77
    So, as I understand it, there is no one right way to do things, I pretty much need to figure this out depending on my needs and the scope of the game.
    Thank you guys.
     
    Gigiwoo likes this.
  5. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    I agree with that. But there are some general rules that are good to follow:
    • If there's even a remote chance that you may need two of something, don't make it a singleton. (This is a form of the good coding practice of decoupling code, as is aer0ace's comment about messaging.) For example, maybe you'll need multiple EnemyManagers for different types of enemies or factions. Or maybe you'll add a second player and need two ScoreManagers.

    • Break down your code into the smallest functional components that make sense. (This is a form of the DRY principle - Don't Repeat Yourself.) For example, your EnemyManager may spawn enemies. But you might also have a PowerupManager that also spawns things. Put your spawning code in a separate component so you don't have to repeat it in EnemyManager and PowerupManager.

    Then again, since this is your first project in Unity, you might just do the minimum you need to get it working, and call it a learning experience. There's so much more to learn in Unity, such as managing art assets, working with the UI system, building & deploying, etc., that you might prefer to simply get this project running and take away whatever lessons you can for your next project. Either way, good luck and have fun!
     
  6. aer0ace

    aer0ace

    Joined:
    May 11, 2012
    Posts:
    1,513
    There's definitely a potential for this happening. Again, there's no immediately correct answer. If you built a system one way, and need to change it to support other systems or design, then so be it. It's called refactoring, and it's natural with software development. Like, if I needed to consider multiple EnemyManagers, perhaps I could instead, keep my EnemyManager singleton, and add a list of sub managers to it, instead, one submanager per type. But what I ended up doing on Horde Rush is all custom functionality is implemented in each Monster type class, so all EnemyManager has to do is call Atttack(), and the Monster classes just call the Attack() implementation for the zombie, skeleton, and werewolf, abstracting away the details into each. And for the ScoreManager, if you wanted to keep it a singleton, you can also keep a list of players, and modify the APIs to support a player index, like SetScore(int playerId, int score).

    There are just so many ways to approach it, and determining which is best is partially based on what you're comfortable with, and partially based on what your other systems need to realize your goals. This is what most beginner programmers don't realize, is that they get the idea that once you build something that works, it's done, and doesn't require any change, and thereby don't foresee or account for extra time for this change. But in reality, every system is susceptible to change, and needs to be taken into account.
     
    theANMATOR2b and TonyLi like this.
  7. Abdou23

    Abdou23

    Joined:
    May 2, 2014
    Posts:
    77
    Thank you guys for all these tips, really enlightened me a lot. My game is not that complicated that it requires multiple spawn managers or score managers. What I want to achieve here is to setup a structure that can make my life easier in the future when I actually start designing the levels or add new enemy types. I'm currently still figuring out unity as a whole and also the best approach to make different classes talk to each other, for example:
    when the player completes a level I want to unlock the next level in the "Level Select Menu" screen, should a "Gamecontroller singleton handle that" or do I physically drag the menu script onto the "Level Manager" that handles each level's logic and tell it to unlock the next level, or should I make a static property in the "Menu' script and access it directly from any of the managers?

    There are other design questions that need to be answered and I don't exactly know what is the best practices regarding all this, therefore, I will just go on and try the approach that I feel the easiest but also the most flexible and see how it goes from there.
     
  8. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    It's not Unity, it's C# programming ;)
    How would singletone know which is next level that needs to be unlocked? If it always knows that not matter what level is loaded without accessing it - then by all means go ahead and make it singletone. Otherwise it's a matter for discussion as you can do it both ways. For example, Component with its GameObject set to DontDestroyOnLoad is not much different from singletone. Especially if that Component has singletone field instance pointing to itself. Or you can create singletone method void NextLevel() which does PlayerPrefs.SetInt("NextLevel", PlayerPrefs.GetInt("NextLevel")+1);

    The best practice in this is making both ways once, seeing their problems on practice and then when making next game/part that requires same question making decision based on what you already know about their pros and cons.

    Practice makes perfect.

    P.S. while discussing it you could've already written both ways and would have seen all problems you don't like and pros you like.
     
  9. Gigiwoo

    Gigiwoo

    Joined:
    Mar 16, 2011
    Posts:
    2,981
    Yep - there's no correct solution. Here's a few tried-and-true top-level objects.
    • UI_Manager - Does what it says
    • Game Manager - Sort of the root. It holds all the other managers, does save/load of preferences, and is the ONLY object receiving an OnUpdate() - which it then sends to the others
    • LevelBehavior - Or whatever. You might call this 'thegameplay' or all kinds of other things. It does the brunt of the top-level work for the actual gameplay.
    • Player - If the player has a physical representation (such as a ship, character, or icon), then you almost always want a single object for the player.
    • AudioManager - something for later.
    Gigi
     
    mondovila, theANMATOR2b and kittik like this.
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I tend to avoid managers. My approach is typically to make a ton of small scripts.

    I do have to have some managers. In my projects they normally take care of the boring bits like making sure the game pauses when the player enters a menu. Or that the game saves and loads properly. General meta stuff that's not related to game play.
     
  11. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    Fascinating. I would have expected someone like you to be all about dem' managers.
     
  12. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    If I need a lot of procedural generation or extreme performance or manual object culling, I do my own managers.
    If I just need a game, I use what tools Unity gives me out-of-box.

    So I agree with both approaches.
     
    theANMATOR2b likes this.
  13. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Nah. I build my code much like a chemical plant. Hundreds of little independent unit operations. Each piece does its job then passes the data on, never knowing or caring what happens to it next.
     
    Rombie likes this.
  14. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    Ah, drawing on your real-world experience! Makes sense. Maybe my time in the Army has influenced me to use tons of manager classes that don't properly do their job and refuse to share data with each other or their members, but insist to the application hierarchy that everything's going as planned...
     
  15. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    That's fascinating. This deserves its own thread. How does your day job effect the design patterns in your game dev.

    I know for me a lot of concepts are borrowed from my day job. Unit operations, systems ect. Heck, I even structure the data flow through my game in a similar fashion to a physical pipe line.
     
  16. aer0ace

    aer0ace

    Joined:
    May 11, 2012
    Posts:
    1,513
    Link to the thread when someone creates it...
    For me, at the large studio that I worked for, my hobby projects tended to use the programming language that I was using at work. For about a year it was all Actionscript, and for about nine years, it was all C++, with some C# and Python peppered in. It served the dual purpose of making something that I wanted to make, and improving my skills for the real job.
     
    GarBenjamin and Martin_H like this.
  17. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436


    (In case the link doesn't work or breaks: it is Rorschach saying "do it" at the end of the Watchmen movie)
     
    Samuel411 likes this.
  18. RockoDyne

    RockoDyne

    Joined:
    Apr 10, 2014
    Posts:
    2,234
    The dirty little secret here, nobody really knows what the best practices are. Both a blessing and a curse, the fact that Unity isn't designed as an engine for a specific type of game also means it isn't built for any game... if that makes any sense. There's no set, or pre-established, way to do anything, so you're kind of stuck constantly figuring out what your needs are at the moment and figuring out how to easily get there from here.
     
    Abdou23 and Kiwasi like this.
  19. Abdou23

    Abdou23

    Joined:
    May 2, 2014
    Posts:
    77
    Thank you guys for all your help, I already started experimenting and found that a singleton is really not needed at this point, I will go with a "Level Manager" approach that handles each level's logic independently, and have another manager in the Main Menu that holds score and other logic and another manager for game Settings Menu, I like this approach the best, every part of the game handles it's own logic, and just make them communicate with each other when necessary.
     
    GarBenjamin likes this.
  20. mondovila

    mondovila

    Joined:
    Apr 1, 2017
    Posts:
    4
    I know this post is from almost two years ago, but its one of the best questions and answers I have run across about game structure. I'm not a programmer, so I ran though some of the build a game tutorials and have learned very basic stuff, but I'm using singletons, animations, scores, high scores, player prefs, physics, particle systems, etc., and I'm having trouble seeing the whole picture, where everything is connected, so this discussion is very good. I wish I had found this much earlier. Its hard knowing what to search for when you start out. Cheers.
     
    codeblue00 likes this.
  21. mondovila

    mondovila

    Joined:
    Apr 1, 2017
    Posts:
    4
    Thanks, Gigi for posting this and the links. :D
     
  22. Ranger-Ori

    Ranger-Ori

    Joined:
    Apr 29, 2010
    Posts:
    29
    Hey,

    This is quite an old post, but I have some insights I would like to share.
    I stumbled upon this problem, of "managing" a level, and realized there's no escape from it.

    What I do, is creating a 'Game Manager' gameobject, and I simply add all the relevant separated components into it.
    "AudioManagment, AnimationManagement, LevelManagement ... " an so on...
    This way, I have all management objects/components in one place, and it's easy to drag prefabs with the inspector.

    I also have some sort of an 'Singleton' object, without actually coding it, cause I don't want to mess things up.