A Unity codebase does not have to be a bunch of “topic related classes”.
Your application handles user input, computing, network operations and must render a frame to be displayed to the user at each frame. You have to separate concerns.
That is, you should try to reduce as much as possible coupling between your view and your logic, and extract your networking operations in a separate bloc. Also always keep in mind that you should design your game module to be reusable as much as possible. You should avoid using the same data structure in different modules and thus you must introduce a way to provide data independence between related modules.
The SOLID principle
Some basic key concept of object oriented programming which sum up these ideas is the SOLID principle :
S : Single responsibility principle : each class is responsible of one and only one task (thus no UI should be displayed by your network interface class)
O : Open/closed principle : each module you develop must be Open for extension but closed for modification, that is the architecture should anticipate further changes and thus provide ways to add new related items in an easy way through inheritance for examples
L : Liskov substitution principle : a subclass must preserve the purpose of its parent class, overrided methods or properties should have the same meaning as in parent class.
I : Interface segregation principle : Define interface by small unique roles, some class should be able to implement it and when doing so implement only methods useful to it.
D : Dependancy inversion principle : High-level modules should not depend on low-level modules, you must introduce some kind of abstraction through some interface. A great explanation can be found here : https://www.oodesign.com/dependency-inversion-principle.html
The Clean Unity Architecture
In order to help you today, I want to focus on how to apply Uncle Bob’s Clean Architecture to game development using Unity.
Let’s simply call it Clean Unity.
This architecture is a response to the need to keep your codebase clean, with single responsibility modules, testable and to organise your code with intents rather than a skeleton of your inner architecture choices.
The view controller, interactor, and presenter are the three main components of Clean Unity. They act as input and output to one another as shown in the following diagram.
The Controller bloc should be the entry point of all use case triggering (except when a use case fires another one internally), it calls the actual use case methods through some layer of abstraction or interface (in green on the above diagram).
We send a request DTO object as a parameter of the function call to also provide data independence (interactor variables do not rely on controller variables directly). This allow us to be free to change the request content with minimal changes, that is by only modifying the request DTO (some C# struct in our case).
The Interactor bloc then compute the data needed to know what we should be displaying, it is the heart of the computing tasks.
Note: if the interactor carries a too complex functionality (exemple: a networking task to retrieve some result) we can also extract some of its internal code to another bloc called a Worker.
The interactor then send the computed data to a presenter bloc (through an interface) and this final bloc is responsible for rendering all kind of feedbacks to the user. In Unity 3D, they can take various forms, 2D UI changes, 3D Transforms movements, Animations, Sounds and so on.
The Initializer bloc simply holds and validate all the references to Unity Scene components and Assets components.
Note: it can also fetch those references dynamically if some gameObject is instantiated on the scene during runtime (though a FindObjectOfType call for example).
The Clean Unity architecture is derived from the Clean Architecture proposed by Uncle Bob. They share many common concepts such as the components, boundaries, and models.
What if you knew exactly which file to open and which method to look ? How much more productive can you be ? Imagine your tests run in seconds instead of minutes or hours. And you don’t need any Unity Package to install.
Buy the Clean Unity Handbook to get a clear tutorial explaining how to implement Clean Architecture in your Unity projects. It will also provide you C# templates to get started implementing your reusable features faster !
In the Clean Unity Handbook, you will learn how to:
- Find and fix bugs faster and easier.
- Add new features easily.
- Write shorter methods with single responsibility.
- Decouple class dependencies with established boundaries.
- Extract business logic from controllers into interactors.
- Build reusable components with workers objects.
- Write fast and maintainable unit tests.
- Have confidence in your tests to catch regression.
- Apply what you learn to new and existing projects of any size.