Search Unity

Structuring Projects...

Discussion in 'General Discussion' started by BlackArcane, Dec 4, 2014.

  1. BlackArcane

    BlackArcane

    Joined:
    Jun 26, 2011
    Posts:
    119
    After so much trial and error and so many abandoned games it's high time I get educated on this. How do I structure my projects? By structuring them, I mean divide the big problems into smaller ones, make a chart of some kind and then start solving each one as a single module. Example:

    Problem: Simulation of car physics
    Layer 1: 1) Simulation of the forces 2) Simulation of the wheels 3) Simulation of the engine
    Layer 2: 1.1) Friction 1.2) Air Resistance 2.1) Friction 2.2) Steering 3.1) Torque 3.2) Gears
    .
    .
    .
    And so on until each problem is simple enough to be solved on it's own. How do I get better at it, which reads do you recommend and finally, is it something that you do on your projects?
     
    Gigiwoo and illinar like this.
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I'm really not sure how to get better at it other than (A) doing it a lot, or (B) having a mentor.

    But you should certainly read up on design patterns and refactoring, if you're not already intimately familiar with those. Just search Amazon and pick some recent-ish books with good reviews (I like this and this, but there may be newer ones that are even better).

    I would say the #1 concept you want to internalize is: hide implementation details as much as possible, so that you can change them without breaking the rest of your program. For example, take the "simulation of the engine" part of your example. The important thing to think about is how that interfaces with the rest of the code. Perhaps you make an Engine class, with a very small number of public methods to return the speed and torque given the accelerator and gear inputs (or whatever).

    Now, your first implementation of that should just be hard-coded in some brain-dead simple way; maybe just a couple of if statements that return fixed speed/torque for each gear, or something like that. You know it's wrong, but you don't care, as long as it compiles and runs and provides just enough functionality for you to work on something else.

    Then you'll cycle back later and replace the dumb implementation with a slightly smarter one that actually simulates RPMs or something. The rest of your code won't care, so you can sit down with just the engine code for an hour or two and focus on that without breaking anything else.

    Oh, and that reminds me of critical concept #2: a software program is way, way too complicated for a human to keep all the details in their head all at once. So this is the second reason you hide implementation details; when you're working on one part of the code, you want to be able to forget all the details of the rest of the code. You only need to know the interfaces (public methods/properties), and those should be as small as possible, to make it easier for you.

    So contrast this approach — dividing the problem into classes/modules with all the details hidden — with a more naive approach, where all your properties and methods are public, classes call into other classes or even change their properties willy-nilly, and so on. Such a project is in a world of hurt because (1) when you try to change the implementation of something, it breaks code that was using the old implementation, and (2) in order to add or change anything, you have to keep way too many details from all over the project in mind.

    So... that was a long diatribe. In answer to your question, no, I don't start at the top and break down the whole giant problem before I start working on it. Instead I use successive approximations, starting with whatever fruit is easiest to reach, and using dead-simple "stub" implementations (as described above) wherever possible to keep moving forward. I keep the interfaces thin and make stuff protected/private as much as possible, and just keep refining until it's done. It probably takes practice, but hang in there — you can do it!
     
    illinar, elmar1028 and Ryiah like this.
  3. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    You're on exactly the correct path by thinking "divide and conquer." When it comes to structuring your project, at this point high level concepts will help a lot more than low level coding tricks. The single best concept I can recommend is decoupling, which is also what @JoeStrout recommends above.

    Two excellent techniques for decoupling are design by contract and test-driven development. (I'm using the commonly-accepted terms to make it easier for you to google if you want to read more about them.)

    "Design by contract" means a module (a class, a component, whatever) is only guaranteed to do a specific thing, accepting a specific input and returning a specific output. Other modules don't care how it does its job, only that it keeps its input/output promise. For example, an air resistance component might accept barometric pressure and speed as input, and return a float in the range (0..1) as output. The higher-level Simulation of Forces component doesn't care how it computes the float; it just knows that, if it gives pressure and speed, it will get a float, with no other data, no other requirements, and no hidden side effects.

    Design by contract is also fun because you can write modularly, creating little toys of each part and getting the satisfaction of seeing something work quickly, and then bring them all together into a larger project.

    "Test-driven development" (TDD) goes hand-in-hand with design by contract. Since you know what a module's contract is, you can write tests that verify that it fulfills the contract. If you make changes to the module and the tests still pass, you can have pretty good confidence that it will continue to work properly with the rest of the project.

    In addition to the three links above, I recommend Code Complete and Design Patterns for boots-on-the-ground programming. Design Patterns is basically a cookbook of reusable designs that have already been thought out and tested. But read up on decoupling, design by contract, and TDD first. The better your high level design, the less low level rewriting and refactoring you'll have to do.
     
    Last edited: Dec 5, 2014
    Jimmy-P, JoeStrout and Ryiah like this.
  4. RJ-MacReady

    RJ-MacReady

    Joined:
    Jun 14, 2013
    Posts:
    1,718
    Just get really good at programming, and really fast with the tools... then you can just do everything through trial and error.

    In all seriousness, you need to know exactly what you're trying to do. Any sort of of "I'll figure it out when I get there" is game suicide. How will you figure it out later when you can't figure it out, now?

    Structure is secondary to understanding the problems you face with implementing each game feature, and understanding the problems pales in comparison in importance to knowing what you're trying to make.

    If you knew exactly what you were trying to do, how could you help but to complete everything you start??

    It's like if someone tells me... draw a bike. So I draw what I think a bike looks like, and everybody says,"That's a S***ty bike." Or if I take twenty minutes to look at the basic construction of a bike, how it's bars line up, how it's wheels attach, how the chain connects to the pedals... then I draw it in a couple minutes and everybody says, "Sick bike! You're really good at drawing!"

    No. I'm really good at understanding, I'm a so-so artist but I'm smarter than most artists who will just sketch and sketch and try to get better through repitition or magic or something.

    For some reason when it comes to computer stuff I've been stubborn as a mule. I keep making assumptions and based on what I read everybody else does the same thing. I don't know if it stems from laziness or just arrogance but a lot of designers fail to actually completely design something... More like get the gist down, hope for the best and just assume our awesome instincts will kick in.

    Now I'm thinking our discussion of game design so far has been only limited to really fluffy stuff, but not any specific stuff... like how fast should x move vs. the player, etc. Hmm..
     
    Last edited: Dec 5, 2014
    elmar1028 likes this.
  5. gmatsura

    gmatsura

    Joined:
    Sep 26, 2012
    Posts:
    15
    You mentioned lots of trial and error and abandoned projects. Are you abandoning projects because you get stuck and are unable to continue? or giving them up because you get bored?
     
  6. Gigiwoo

    Gigiwoo

    Joined:
    Mar 16, 2011
    Posts:
    2,981
    What if you're asking the wrong question? If you struggle to subdivide your project, then it's possible you're not quite skilled enough to be tackling a project of that size. On the one hand, that hints at Deliberate Practice. On the other, a key part of Deliberate Practice is tasks that are ALMOST beyond your ability. If you find you aren't finishing your projects, then likely, it was BEYOND your ability, which isn't the most effective path for growth.

    TL;DR - BUILD A SMALLER PROJECT! Finish in 4 weeks. Ship it.

    Gigi
     
    GarBenjamin likes this.
  7. GarBenjamin

    GarBenjamin

    Joined:
    Dec 26, 2013
    Posts:
    7,441
    @Gigiwoo makes an excellent point. I have been developing for a long time now and always prefer small simple projects. Whether games, utilities, biz software etc. It is just far more enjoyable to focus on making a simple project and getting it done in a timely manner. For my game projects I will max out around 3 to 4 months on a single project... maybe 175 to 250 hours total. The only way I'd do an epic game is by working on it for a 4 to 6 weeks then take a break and knock out a very small scale project. Then return to the big project for another 4 to 6 weeks. But I think 50 to 150 hours is my ideal project time.
     
    Gigiwoo likes this.