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

Design decisions where to put code

Discussion in 'General Discussion' started by Louhikarme, May 7, 2014.

  1. Louhikarme

    Louhikarme

    Joined:
    Apr 21, 2014
    Posts:
    4
    Hi everyone,
    I recently started with Unity3d. There are loads of vids i've done and few tutorials. And I made my own Pong prototype. With Pong things were relatively simple, make an object, slap a code in it and things work (after few hours of error seeking).
    Anyway, I then started on thinking of the said Pong and looked all the scripts and the project layout i had, and got me thinking of in bigger projects that i basically would have loads of lines of codes of different things, what would be principal idea of keeping code separated on each object and not writing single script that does everything.
    What i'm getting is that if now have 5 scripts in my prototype, but i could stuck them basically in just two, or even one just tweaking the code portion.
    So where would you draw the line to keep scripts on certain tasks and then maybe have "the game" script calling on from them.
    Or is this something you just grow on with the experience of doing things and seeing what works and what doesn't.
    Thanks for reading. :)
     
  2. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,543
    This whole school of thought of making code organized is under software engineering. If you would make a house, you wouldn't put a kitchen sink beside the bed, right? The plumbing would be a lot more hassle that way. You put things where they make sense. It's the same idea with code.

    It's simply about making code easy to read, easy to debug, and easy to modify. Code in such large software as games is inherently complex, so the trick is to manage that complexity.

    There's a few guidelines that may sound non-sensical:

    Place more importance to readability than "clever" code. A big bulk of time is spent *reading* code, and it pays to make it easy to read.

    That means limit making those single-letter variable names, and don't squeeze so many things happening on a single line of code.

    Name your functions/variables/classes well. They doubly act as self-explanatory documentation.

    A class should have only one responsibility and do it well. http://en.wikipedia.org/wiki/Single_responsibility_principle Also see: http://en.wikipedia.org/wiki/Separation_of_concerns

    A method should do one thing only. If it looks like it's doing two things, put each in a separate function.

    A class shouldn't expose it's inner details to outside code. Think of it as this: you're in a restaurant, ordering something, perhaps a chicken. The chef takes care of all the details of cooking the chicken, you don't need to worry about how old the chicken is, where it came from, etc. You don't pester the chef about it, you just want to eat a cooked chicken.

    This means interactions between classes should be well thought out. Class A wants to call a function from class B, so it supplies class B with so and so arguments, and expects class B to return so and so values. Class A shouldn't care how class B does it. Class A shouldn't mess around with class B's variables.

    There's a lot more to that. I suggest you pick up a book like "Code Complete", or "The Pragmatic Programmer". They're big so expect a lot of reading. If you want something more introductory, try "Head First Design Patterns"


    ----


    It should be noted that when you're prototyping, you can forget about all that. This making-code-organized only makes sense once you decide to flesh out the whole game.
     
    Last edited: May 8, 2014
  3. MarkrosoftGames

    MarkrosoftGames

    Joined:
    Jan 5, 2012
    Posts:
    442
    you could take a look at some fully finished tutorial/sample/demo projects to see how they do it.

    its usually a good idea to keep things separated and simple. the idea of having something do one thing and do that one thing good is not a bad concept. but it can vary greatly in how you actually execute it. should x functionality be broken into individual game objects, different methods within a class, or maybe separate scripts on the same object, or should it just be all in one because each part is small enough that having it all together isn't a big deal?
     
  4. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,543
    That's the basic idea, but how to do it is up to you, and certainly depends on the particular situation. What "one responsibility" is in your situation, is up to you to define.

    Part of it is the wisdom to not over-engineer things. The answer is to that question is: do it only if it solves a headache for you.

    Just reading up on the concept won't automatically make one a really good programmer. Like I said, to anyone who's curious, check out those books I mentioned, they explain such things in greater detail.


    Generally, classes with thousands of lines of code is a no. Functions with 10 or so arguments is already stretching it. When your code is getting unwieldy, that's a good indication it's time to see if they should be broken down to more manageable pieces.

    If you have a function that needs to do some preparation on the data before it can start to do any work, move that "preparing" to a new, utility function. Having that code as a new function, with a descriptive name, makes your intent much clearer to the reader.
     
    Last edited: Jun 17, 2014
  5. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,543
  6. RockoDyne

    RockoDyne

    Joined:
    Apr 10, 2014
    Posts:
    2,234
    It would be nice if there were larger/complete projects out there that documented their design practices more.

    Welcome to the world of unity development, where you throw out ninety percent of object oriented practices when you first start and slowly piece it back together over time. You are basically staring at the central conundrum of unity development, which is autonomous game objects versus hierarchical puppet masters.
     
  7. jmatthews

    jmatthews

    Joined:
    Jul 27, 2011
    Posts:
    199
    It's quite a challenge. The other issue I run in to with Unity is the "balkanization" of code. Where like functionality tends to get spread so widely across your project you end up re-inventing your re-invented wheel.

    Ultimately you need to bias yourself towards code that is simple to reason about. The trick is to determine what exactly that means to you. There is no right or wrong answer, just generalizations that often hold true.
     
  8. wccrawford

    wccrawford

    Joined:
    Sep 30, 2011
    Posts:
    2,039
    In general, I place my code so as to keep the complexity down.

    Throwing a ball has hardly enough thing to do with running and jumping, so those are clearly separate scripts, IMO, even though they're both used to control the same character. Then, if something's broken with throwing, I don't have to also debug the running and jumping.

    In general, keep concerns separated. If something special needed to be done while jumping and throwing, I wouldn't combine the scripts. Instead, I'd expose an isJumping variable on the jumping script and read it from the throwing script.

    Finding the exact line of where to separate things isn't a science. It's more of an art. And just because you combine them now doesn't mean you won't realize the complexity later and separate them.

    Another thing I like to do is separate 2 halves of something so that one half or the other can be re-used. For example, ringing a doorbell. I'd have a script on the player that is used to send and 'activate' signal to the doorbell. Then, when I implement the door's 'open' function, it can also react to that same 'activate' signal. The script on the player would send 'activate' to whatever the player is currently aimed at. Then I only have to write the code to determine where the player is aiming once, and if it ever breaks, I only have to fix it once. There may be other complexity that gets added, such as playing a certain animation when activating which differs by object, but that can handled by having that data on the object as well. If different entities had different animations to play, then perhaps separating that out into a lookup table would be better.

    As complexity grows, separate things.

    The more you program, the more you'll have an innate sense of when things will get complicated.
     
  9. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,543
    I had the experience that the way schools teach object-oriented practices did not explain it very well in the context of game development.


    Games are so varied, there's no one technique that is a best fit for everything. It's hard to recommend something without citing project we can look at.

    However, generally, deep hierarchies are looked down on these days. It's become a by-word: favor composition over inheritance. (Unity's component-centric approach helps with this)

    But don't get too caught up in that. It's really about being mindful of why you decided to go with this or that when there are alternative designs. Even if you go with some unpopular design, at the very least you better have a good reason other than "I just felt like it".
     
    Last edited: May 7, 2014
  10. JovanD

    JovanD

    Joined:
    Jan 5, 2014
    Posts:
    205
    I mostly make a lot of little scrips and there always on the place where the code is doing something. Also i brake my design in to sectors, so if i for example have a script that spawn enemies, it's gonna be called like "sectorXX_spawner", as for asset management, i bundle everything in to one huge folder and use search function when i need something XD
     
  11. RockoDyne

    RockoDyne

    Joined:
    Apr 10, 2014
    Posts:
    2,234
    Considering that I was taught OOP concepts strictly within the context of game development, I would have to say the component nature of unity doesn't present itself as a perfectly sterile environment for OOP. It takes a while to wrap your head around the siloed nature of gameobjects and the tenuous characteristics of getcomponent, before you can actually reapply typical design patterns.
     
  12. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    It depends on one hand you can have a behavioural component structure, where scripts define behaviours that act on game objects. So if you want a bullet that does Damage you add the damage component. And if you have a grenade that does ranged damage you add an explosive component.

    But then you can get into problems of communication e.g. Damage only effects components with health but when health hits zero it needs to tell the gameObject that it has died, and sometimes it's best to have a more complex component that just works.

    Then there are considerations for memory usage and optimisation that need to be factored into your game design. So it's a balancing act.

    But from personal experience there is nothing better than putting together a set of interacting components that can work as a toolkit on your project and give you the flexibility to have fun.
     
  13. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,543
    Yeah, I wouldn't derive all my classes from MonoBehaviour. As with anything, there are appropriate moments to use it.

    And I wouldn't go around looking for something *perfect*, because everything has trade-offs.

    But overall I've had better experience with Unity, than, say, the Torque Game Engine. It gives me a much cleaner slate to start with, but not too bare like OGRE or CrystalSpace.



    It depends on what you decide a "component" to be. You can make it as fine-grained as that, and depending on the kind of game it may make more sense to do it that way, but I personally would be fine with having a Weapon or Projectile Component that simply calls a Damage function on the Character.

    If in your game, there are bullets that can heal instead of damage, then it makes sense to separate damaging as its own class, so you can swap it out with a "heal" class, which is then attached to the Bullet class, for example. You don't need to make those damage/healing classes as MonoBehaviour scripts/components, they could very well be just standard classes, existing as variables of the Bullet class.

    And like I said, you only do these things if they solve a headache for you. Since it gives you the ease of swapping out what a Bullet does (in the hypothetical example I mentioned), then it's something worth doing some software engineering with.



    C# has built-in commands for this (events/delegates).

    I use the open-source library StrangeIoC, which takes that a bit further. There's also uFrame in the Asset Store but that one's quite expensive.



    I get this feeling Unity should have had a built-in pool manager by now.
     
  14. Louhikarme

    Louhikarme

    Joined:
    Apr 21, 2014
    Posts:
    4
    Thanks everyone an great input. What i can take from this that i was thinking along the same lines. Just needed some confirmation and extra reading. i'll be checking those books, already read the rts bit @anomalus, good stuff.
    Having 15 years of system admin experience I haven't needed to code anything, other than make batch files. So finally getting more serious stuff, I like to make some research of best practices, from many people, not just one. Since It boils down to what you can grasp. And the programmig has been always the achilles heal of mine, and in my work, i haven't needed it. but life changes so learning new stuff, but i don't want to invent the wrong wheel again if there is proven things you can use.
    Thanks again everyone. :) going to kick those bloody arrays to a pulp. :)