Model View Controller (MVC) Design Pattern
The model view controller is a very common design pattern that has been around for quite some time. This pattern focuses on reducing spaghetti code by separating classes into functional parts. Recently I have been experimenting with this design pattern in Unity and would like to lay out a basic example.
A MVC design consists of three core parts: Model, View and Controller.
Model: The model is a class representing the data portion of your object. This could be a player, inventory or an entire level. If programmed correctly, you should be able to take this script and use it outside of Unity.
Note a few things about the Model:
- It should not inherit from Monobehaviour
- It should not contain Unity specific code for portability
- Since we are avoiding Unity API calls, this can hinder things like implicit converters in the Model class (workarounds are required)
A custom Vector3 class to use with our data model.
View: The view is a class representing the viewing portion tied to the model. This is an appropriate class to derive from Monobehaviour. This should contain code that interacts directly with Unity specific APIs including
- Typically inherits from Monobehaviour
- Contains Unity specific code
Controller: The controller is a class that binds together both the Model and View. Controllers keep both Model and View in sync as well as drive interaction. The controller can listen for events from either partner and update accordingly.
- Binds both the Model and View by syncing state
- Can drive interaction between partners
- Controllers may or may not be portable (You might have to use Unity code here)
- If you decide to not make your controller portable, consider making it a Monobehaviour to help with editor inspecting
Now that we have all of the main pieces, we can create a factory that will generate all three parts.
And finally we can call the factory from a manager...
Attach the Manager script to an empty GameObject in the scene, right click the component and select "Load Player".
For more complex logic you can introduce inheritance with abstract base classes and interfaces for an improved architecture.