Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[SOLVED] Best Code Structure for my Project?

Discussion in 'Scripting' started by BumblePux, May 16, 2019.

  1. BumblePux

    BumblePux

    Joined:
    Jun 14, 2017
    Posts:
    5
    Hello Unity Community,

    I've worked through a number of game dev tutorials for the last couple months and have also read all sorts of articles etc. on code structures, best practices, and so on.

    With this in mind, I've been working on my own small game and due to the type of game it is, and from having read various varying thoughts on multiple topics, such as "avoid managers/singletons", "keep components reusable", "complete decoupling" etc. I seem to have confused myself and am unsure what the best code structure/architecture would be for my particular game.

    The game concept is simple. It's a tap/click reaction game, where a green square rotates in a circle, and the player must click when the green square has collided with a yellow square. For brevity, let's call the green square the "player" and the yellow square a "star", but note the "player" is self controlled and the user does not directly manipulate the player.

    I have managed to get the player rotating, and when the player has collided with the star and the user clicks, the star then moves to a new random position of the circle which the player rotates on. Awesome.

    My self induced trouble is now with how to control the other aspects of the game and how to control all of this.
    This is what I want to have happen:
    Game starts, a timer with an initial start value begins counting down, the player is rotating in a circle and a star has spawned. User clicks when the player has collided with the star. The result:
    - Play "success" sound,
    - Increase a score value by 1,
    - Change the player movement direction (clockwise to anticlockwise and vice versa),
    - Increase player rotate speed,
    - Star spawns to new random position of the circle,
    - Increase remaining time by specified amount.

    And if the user taps but misses, this should happen:
    - Decrease remaining time,
    - Do camera shake
    - Play "missed" sound

    If timer reaches zero, game is over. Show a game over screen.

    Previous tutorial pages would tell me to just have a singleton "GameManager" object which references everything and takes care of everything. Other articles etc. would then lead me to believe all projects should contain scripts doing just one thing (single responsibility) to isolate each specific game function/feature.

    Sorry for the long setup, but my question is... is it "right" to have this singleton god GameManager, or should most game projects have a script for each game function/feature? If the god class should be avoided, how can the separate game function pieces communicate whilst being manageable and not become a messy, spaghetti mess? Is there a thought process I'm not following or have I been reading incorrect information.

    I'm sorry this is more than a single question, but I believe these questions are kind of inter-related?

    Many thanks in advance for your responses,

    Adam.
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    You should know that for all three examples cited, that advice is less and less valuable the smaller and simpler your project is. If you're making an open world MMO with a codebase you expect to use for the next 5 years, yes, follow all of that advice heavily and structure your code robustly or you will die. If you're making a simple puzzle game, you can (and possibly should) take more shortcuts. If you're making a one-day hackathon prototype of a game, frankly you should follow none of that advice, it will only waste your time.

    All of those pieces of advice should come alongside reasons behind them, appropriate times to ignore the advice, and knowledge of the tradeoffs involved. If the advice came from someone that did not include that side information, that person is bad at giving advice.

    To more specifically answer your question, it definitely seems to me like the sort of situation where a singleton/manager is fine to use.
     
    lordofduct and Ryiah like this.
  3. Pixsaoul

    Pixsaoul

    Joined:
    Feb 10, 2014
    Posts:
    14
    Hello,
    I completely agree with @StarManta about the necessity of taking the scale of your project into account.

    If you're going for a quick prototyping of your game, for simple playtesting and analysis of your gameplay, then anything that works is good. I would still recommend not using singletons but have explicit references between your objects, using [SerializeField] private, and if possible have these dependencies go one way only (A knows B, can call B methods, but not the other way around, if B needs to communicate something to A, A should have provided some callback to be invoked by B).
    It is not harder than using singleton, it just force you to drag ndrop some references and it helps a lot when debugging (singleton error management makes it hard to understand the stacktrace sometime).

    If you are going for a medium size project, that you need to understand the structure in the end, it would be a good idea to split classes as small as possible and identify their purpose clearly.
    Example : Have a MenuView that contains all the buttons on your menu (Play, Settings, Exit) and have a SceneManager that is reponsible for which scene gets loaded, this SceneManager references MenuView, and provide method callbacks for when selecting Play for instance.
    You can also externalize the actual loading of the scene into a SceneLoaderService that have load methods, where you manage the unity calls and parametrization, and have the SceneManager methods call this service when requesting something.

    When going for big project, it is important to setup different layers of application: Data (Domain model), Presentation,
    Business logic, Transverse utilities. With that in mind, I strongly recommend the SOLID concept to keep things clean and scalable.

    Personally I use StrangeIOC as injection framework, combined with IUnified to allow a general use of interfaces in Unity and keep dependencies in the right order.

    Hope that helped "^^
     
  4. BumblePux

    BumblePux

    Joined:
    Jun 14, 2017
    Posts:
    5
    Thanks for your responses. They are both very helpful, and I appreciate the explanations and advice regarding different size projects and methods to follow. Of course this particular personal project is a small one as the start of my game dev journey, but I've been intrigued to know how this can differ when moving onto larger stuff moving forward and how the ways of thinking about the interactions change, given project scope.

    Thanks again!
     
  5. Pixsaoul

    Pixsaoul

    Joined:
    Feb 10, 2014
    Posts:
    14
    My guess would be to start with a demo fully throwable and then start to do a medium size project, with responsibility divded. As long as everything is divided, you can enhance each part of your project separetely and avoid a huge horrible period of global changes to your project.
    for example you can skip the interfaces at first, and add them later on when you realize you need to ahve multiple implementation / you want a bit more abstraction.

    Your welcome ;)