Every so often I encounter a programmer who seems semi-fond to excited about the subject of MVC in Unity. I have also been asked to describe the merits of MVC in the context of Unity during multiple job interviews. I personally think that the attempt to adhere to MVC in Unity is actually a misunderstanding of MVC and object-orientation itself.
MVC has good concepts in it. Separate database objects from objects which draw a GUI. Separate those from objects which interface between the two. The logic behind MVC is good, but that logic, it’s resulting abstractions and system metaphor were conceived of for 2D GUI. The purpose of an object-oriented architect is to design abstractions and the system metaphor to be as congruent with the problem domain they are trying to solve as it possibly can. Given that 2D GUI is a very different problem domain from a 3D interactive environment, why would anyone expect the abstractions created for a 2D GUI to be the most ideal for a 3D interactive environment? I don’t think they are.
I believe people who carry MVC from 2D GUI into the realm of 3D interactive environments do so because they do not understand that is why the concepts of model, view and controller came to be. That they were abstractions designed to describe a system which very literally was a system to describe coordinates to draw things, the view. A system to access a database, the model. Then a system to interop between the two, the controller. It was not intended to be universally applicable, it came to be falsely seen as such by some because architecture of 2D GUI became a huge part of software development, many developers spending the majority of their career doing only that. Thus they then falsely presume MVC applies to everything, because it did in the problem domain they specifically worked in primarily, thus they are now seeing everything through the MVC lens. If you do this I ask you to stop and step back. A 3D interactive environment is not a 2D GUI. A good object-oriented architect should create a new set of abstractions specific to their problem. This is why I state someone trying to take MVC to 3D interactive environments is actually misunderstanding MVC and object-orientation itself.
Now to step through the concepts of model, view and controller independently.
View. This is one of the worst aspects of it. Because what is your View? Keep in mind in the context of MVC a view class describes how to draw a 2D GUI, it has the hard coded positioning, or math to determine placement of elements on single window. The equivalent of that in Unity is your GameObject hierarchy, transforms, and all of the visual components on them. That is what literally draws your game world. Maybe you could argue that your Camera is your View, this is appropriate. But that is also called a Camera, well named already, and certainly doesn’t need a View class describing placement of visual elements to make it work. There is no equivalent of an MVC View in a game world without making an incredibly contrived leap of contortion to do so. It’s just bad form. Now I do use the term view in my Unity projects personally, as it is a good term, but it does not resemble an MVC view in anyway.
Model. This is not a bad concept by itself. If you have a database in your game, it should be contained in an Object. Conceptually a Model object is just fine in a game. But why call it a Model? That is already reserved for 3D Models.
Controller. The problem with this is that, outside of an object which encapsulates a database, and your GameObject hierarchy which describes how to draw what your camera views, everything is a controller. Everything is implementing the logic to control what you see. The script on your car named, hopefully, Car, is obviously controlling your car. The script on your Player named, hopefully, Player, is obviously controlling your Player. If everything is a controller then the word is just clutter. Of course your script on a GameObject is controlling something. This doesn’t mean we need to then have every single script in the project, except for those encapsulating a database, ending with the word Controller or Control. It would be much better if those characters were simply omitted and replaced with other characters more exactly descriptive of what that object actually is, or just have the name be shorter.
I have seen some people reserve the word Controller for more centralized objects which control many things. This is a somewhat more reasonable adaptation of it, versus just appending Controller on almost every one of your scripts. But the times I have seen codebases doing this, the person was actually just using the term Controller to mask what were really God Objects, and poor architecture.
Someone might be thinking, but what if I have a 2D GUI in my Unity game? Well if you are using a web UI framework and you are in the paradigm of web application architecture and 2D GUI, that is a great exemption to this criticism. If however you are using Unity UI, much of the same still applies. There is no View class, that is your GameObject hierarchy containing Unity UI components. For your controller, just name it what it is. GameMenu, PauseMenu, NetworkUI etc.
I have encountered some who argue for MVC as a way to create Unit tests for Unity. But separating out logic to be unit tested is not unique to MVC, and it is not necessary to conceptualize your entire application into models, views and controllers to unit test it. For example, you could have a Car MonoBehaviour, in it an Engine object and a SteeringModule object, their logic self contained and unit testable. To unit test your Engine and SteeringModule you can create a MockInput object which can stand in for typical UnityEngine.Input usage. Here we have now defined the abstractions of Car, Engine and SteeringModule for a car. These are much more congruent abstractions to the problem domain than say, CarController and CarView, which would not in anyway resemble what a view actually is in MVC.
This is why I say, forget MVC in Unity. Conceive of your abstractions for the specific problem domain. You are not bringing merit to your design by choosing very popular key terms from other problem domains and abstracting them even further to fit something different. “It’s good because it’s MVC” is an entirely incorrect statement. “It’s good because it’s system metaphor and abstractions are very descriptive of it’s specific problem domain” is a much better statement.