Better Practices

Last modified by Maarten Struijk Wilbrink on 2021/11/25 16:42

Staying sane in a growing project

Without proper care, a Unity Project can grow unwieldy within a couple of days of development. Below are a few general practices that can help you staying on top of things. 

One general idea which can be helpful is that none of these practices are goals in and of themselves. This means that each practice should serve a tangible benefit to you as a developer, and is not a requirement in and of itself. 

Organizing your Project

You can organize your project in multiple ways. There is no right or wrong answer, but here are some general tips, which may help you in later stages of development. 

Smaller projects: Organise by Type

A good solution for smaller projects is to create folders for the various types of files you’re using in your project. You may create folders such as ‘Scripts’, ‘Materials’, ‘Prefabs’, ‘Scenes’, ‘Data’, etc inside of your Asset folder:

  • Assets
    • Data
    • Materials
    • Prefabs
    • Scenes
    • Scripts
    • Tests
      • Editor
      • Runtime

This method is often seen in online tutorials, and are an excellent way of maintaining an overview of the various files in your project. It makes searching for what you need easy. For instance, a C# script lives in the ‘Scripts’ folder, etc. 

This strategy falls to pieces when your project grows, or if you want to reuse various pieces of project A in project B. You encounter two big issues:

  1. Dependencies are not kept in check
  2. Files that together create specific function are mixed up with all other files, reducing the possibility for reuse in other projects. 

Larger / multiple projects: Organise by Function

To counteract the above mentioned issues, you can create subfolders for each ‘function’ or ‘section’ of your project. Those subfolders can then contain a similar folder structure as the ones mentioned above. So if your project has files related to ‘Characters’, ‘Data’, and ‘UI’, you might create something like this:

  • Assets
    • Data
      • Prefabs
      • Scripts
      • Tests
        • Editor
        • Runtime
    • Characters
      • Materials
      • Prefabs
      • Scripts
      • Tests
        • Editor
        • Runtime
    • Scenes
    • UI
      • Materials
      • Prefabs
      • ScriptableObjects
      • Scripts
      • Tests
        • Editor
        • Runtime

This practice promotes separation of responsibilities, especially if you combine this with creating separate Assembly Definitions and Namespaces for each ‘function’. 

Avoiding a spaghetti mess

Spaghetti Code is the term used for code which has a lot of (inter)dependencies. Like a bowl of spaghetti, it is very hard to see where each piece begins and ends. Trying to make small changes in spaghetti code is hard, and often results in a lot of broken systems. 

Our goal is to create code that has few dependencies, and which can (theoretically) be easily swapped out for other code, without breaking many (or any) other systems. 

There’s a lot of good theory and practices to learn. Have a look at these two excellent resources The Pragmatic Programmer by David Thomas & Andrew Hunt and Clean Code by Robert C. Martin if this is something that you’re interested in. 

They explain in practical examples how to implement a core concept: Make your code easier to change. Consider often if what you’re creating at that moment is helping the project become easier, or harder, to change. For our purposes, this does not only apply to code, but to our entire Unity Project. It also applies to being able to easily distribute what you make to (your own) other Unity Projects.

One way to create better code, with fewer dependencies, is using a few well-placed Design Patterns. An excellent online book on using Design Patterns is Game Programming Patterns. The examples are in C++, but are generally quite straight forward.