Unity Design Patterns

I'm sure many of you are aware of the excellent "Gang of Four" book, Design Patterns. Is there was a similar resource for Unity?

I'm an experienced programmer and always find it useful to read others' solutions to problems. Now that I'm learning Unity with my boys, it would be helpful to be able to implement without having to re-invent the wheel, so to speak.

If there isn't a resource available, it would be helpful for others to post their patterns.

Patterns that I'd be interested in:

  • HUD design: what does your HUD class look like?
  • Victory conditions: where do you put the logic to see if the game is over?
  • Asset management: how do you organize your projects?
  • Tutorials: what is a good strategy to provide a game-play tutorial in your app?
  • Reuse: ideas on how to reuse scripts/prefabs/levels, etc
  • Turn based games: how should a "I go, You go" game be structured?
  • Animation: tips and tricks on character animation (like the 2d tutorial)
  • AI: not algorithms (other good resources), but how to implement in Unity?
  • ...

Each of your bullets is to me a seperate question, so please refraise it or perhaps make each a new question and go a little more in details with your actual question.

As I think your question is far too complex for ONE correct answer, I will try to answer most generic possible.

Use STATE-machines. Periode.

How? First list the states you need for your "machine" (think of them as GEARS in a GEARBOX, only one is possible at any time pr. object)

enum GameState
{
    MainMenu,
    Intro,
    Tutorial,
    GetReady,
    LevelRunning,
    LostLife,
    GameOver,
    HighScore,
    Credits
}

Then a "object global variable" to keep this state inside the object. In this example I have an empty GameObject called "Game", which runs the main application.

GameState state=GameState.MainMenu;

Now I use Unity's Update per frame function, to see what should happen at any given frame.

void Update()
{ 

   switch(state)
   {
    case GameState.MainMenu:
         break;

    case GameState.Intro:

         break;

    case GameState.GetReady:
         break;

    case GameState.LevelRunning:
         PlayerInput();
         PlayerMovement();
         EnemyBrain();  // find targets, change directions, movement.. AI stuff
         EnemyMovement();
         ShowPositions(); // transform every moved object (this could be done in the movement part too, but sometimes collisions etc. are easier to handle first and then only update the positions after finishing calculations. eg. a Pool-table with balls.

         break;

    case GameState.LostLife:
         break;

    case GameState.GameOver:
         break;

    // etc...

   }
}  

then you use a StateChanger too:

void StateChange(GameState newState)
{ 

   switch(newState)
   {
    case GameState.MainMenu:

         break;

    case GameState.Intro:
         goIntro.audio.play();
         ShowBillboard();
         break;

    case GameState.GetReady:
         break;

    case GameState.LevelRunning:
         break;

    case GameState.LostLife:
         playerLife--;
         if (playerLife<0)
         {   
              StateChange(GameState.GameOver);
         }
         else
         {
           // show death sequence
           // then go to GetReady state  
         }
         break;

    case GameState.GameOver:
         goGameOver.audio.play();
         // and wait until done...

         break;

    // etc...

  }
   state = newState; 
}  

OK, sorry to answer my own question, here's a design pattern I thought would really clever.

Context-based foot sounds.

In the 2d platformer tutorial, the sound played when the character walks across a section of platform is a property of the platform. That way the character doesn't need to know anything about the types of platforms and the noise they should make, all he needs to do is find the sound attached to the surface he's interacting with.

I thought this was very clever and extensible way to do this.

Your question really is too broad to be answered here. As a result, my answer is going to be a bit too long as well.

Still, I understand your perspective very well and besides pointing you to the reference manual (best place for understanding unity) or online tutorials (many great ones), I will try to answer to give you the "mind picture" (aka what we used to call the paradigm) for Unity and some for game coding in general.

In general game programming is like traditional simulation programming except more specific tricks of the trade. As I'm sure you know most software Design Patterns are already incorporated or used. Unity has its own way. Also, it is not restricted to games. Its strengths are the ability to organize a wide variety of asset (multi-media including 3d animated/boned models) types in 3D space.

So, for someone who is already experienced in programming, there are ways to keep you from re-inventing the wheel. First of all, you should be aware the Unity is a framework that is heavily data driven. The bulk of most games is done in the IDE. Much of the association, composition that you would get in traditional programming happen through either 1) direct drag and drop of components, 2) exposure of fields (public) that auto-magically enable you to drag objects/components onto or 3) searching in your code for instances of objects and their corresponding script components through methods.

That said, as a programmer, I would first explore Unity from a non-programmer's perspective. Otherwise you may lose access to much of its strengths. You don't want to make the mistake of programming "down in the trees" when you need to get a bit higher to "see the forest". :-)

I like the above answer (by BerggreenDK), by the way, for how a game might be organized. Still, I would (kind of) through many of those states away (in a sense) by incorporating those concepts in their own scene. This way, the main game scene (or levels) can use a more complex state machine. For the game itself, I would also have a GameState script that can be re-used across the levels. To do this, make an Empty Object and put a GameState script in it. Then make that whole composition a prefab.

As a pattern (of sorts) I see each game level as a particular kind of scene. A scene can also be a start up screen, but a level is not. A level is a mind construct (as well a particular scene.) That is, a scene is a Unity construct that is a collection of data/assets arranged in a particular way. This is canonical Unity. A scene is what you see and are working on at any particular time. It ends with ".unity" and is just one of the assets in your project. A project is pretty much just a directory, where Assets is the one sub-directory you deal with but the other important one is Library (which you don't want to treat as a temp throw away, but instead keep it around at all times).

Caveat: Assets and Library sub-dirs are important, since apparently not everything in your .unity file is actually stored there, but is also stored in some weird way in the Library folder. I say this to you specifically, because coming from a traditional background you might think that the Library folder is just support dll's and forget to back it up too. Big mistake which I made many times the hard way. :-(

For Turn-Based Games: To the above answer I would add player number within the player LevelRunning and LostLife states. Like:

player[currPlayer].life--;

Organization of assets is just like any other data driven solution: Use hierarchy. In Unity, this means that your project assets (see project window - not scene) mimic a good directory structure of your chosing. The project is data used across all scenes (therefore levels). Look at is a your collection to make your game. You can organize it by scene (just add a sub-directory). If you have shared assets, across levels, simply add them to some directory named /Shared. I also have a directory for Models, Sounds, Materials, Textures. You'll find that for Models, it may make sense to have their materials under them.

Finally, you will want to read elsewhere (again start with manual and "getting started" areas) about the Object/Component paradigm (all object you see in your world are Object which minimally have the Transform component for example) and get into the habit of using prefabs (create prefabs the moment you have a nice collection of components in your object and may possibly want to use it in a different level, or re-use it in code, or by drag/drop).

Nothing above is meant to be memorized, but just to help give you that "big overview". Hope it helps. :-)

One core Design Pattern applied in Unity Engine is the Decorator Design Pattern. Unity Engine’s Component system is a form of Decorator Design Pattern.

This book has mentioned this.

I’m not even sure how awesome this is or not because I can’t find too many folks who are using patterns in Unity but I made a version of the Strategy pattern for a class I teach and I put it up on git, if anyone would like it.

A Behavior Tree is a common design pattern used in medium to large scale games. A Behavior Tree is similar to a State Machine, however it is much more powerful. State machines suffer from not allowing reusable transitions. Each transition is ‘baked’ or ‘hard coded’ into the machine (or within code as you may notice from the answer posted by @BerggreenDK).

A Behavior Tree is a hierarchical state machine. For example, the top level behaviors of a Behavior Tree for a monster might be idle, alert or attack with each node breaking down into its respective parts. Now image that you have two monsters that only differ in their attack behavior. With a State Machine, the differences would have to be hard coded or baked in. However, with a Behavior Tree, changing the behavior is as simple as replacing the attack node with a new behavior.

This design pattern also allows complex behaviors to be assembled at run-time. Image that you have several idle, alert and attack branches to choose from. You could then choose behaviors randomly or through a configuration when constructing the tree. Therefore, complex characters (and all of the supporting behaviors such as sounds, animation clips, hit point damage, weapons, etc…) that come with each behavior can be built on the fly.

If you search for Behavior Trees, you are likely to find plenty of examples on how to build and use them in video games. There are also visual Behavior Tree editors available from the asset store.

Recently I have been studying a bit about design patterns, I don’t happen to have answer for all problems/requirements but I do have for some:

HUD design: what does your HUD class look like?
Victory conditions: where do you put the logic to see if the game is over?

  • For HUD design and victory condition you can use Observer Pattern, the basic idea is that you should use the observer pattern when you need many objects to receive an update when another object changes, like for health change, coins collected, level completed, etc. There are various ways to implement Observer pattern like creating pure observer/subject class(not inheriting from monobehaviour) or once using monobehaviour. The one way I find most simple is to use scriptable objects as game events and then registering those to listener/observer. For more information on scriptable objects and using those as game events(for observer pattern) you can search for Unite Austin 2017 - Game Architecture with Scriptable Objects, in youtube. Really good stuff.

Reuse: ideas on how to reuse scripts/prefabs/levels, etc.

  • For resusing Scripts you can Use Type Object pattern, lets say you have a game where there are 4 type of dragons, each behaves different from another, so instead of creating 4 totally different classes, what you can do is create once single Dragon parent class implementing features common for all and for ones the features are not exactly same you can mark some methods virtual and use that parent Dragon class to inherit your Base classes which are each different dragons. I did the same in one of my game. Basically you use polymorphism here.
  • For reusing Prefabs, you can use Nested prefabs, extremely easy to implement, more info on this can be found here: Unity - Manual: Nested Prefabs
  • For reusing scene, that is having a single scene acting as different levels, you can use some Game Config file, here scriptable objects will be extremely helpful, you can store the information about each level in the game config file and use that file according to the level you want to play. Taking the dragons example, say at level 2 you want to have a different background, different sprite for dragon and so on, but basically the controller and image component for background are same, so using that config that you can use different image for dragon and background on the fly.

Turn based games: how should a “I go, You go” game be structured?
For this you can use an integer as counter and incrementing it on each turn/ply. Then using that integer to decide the turn,
if(counter % 2==0)
I_Go();
else
You_Go();
If integer value is even the I go, if integer value is odd you go, or maybe vice versa.