MVP
What is it?
Model–View–Presenter, or MVP for short, is an architectural design pattern used to keep UI code more organized. Its main purpose is to divide a screen into three separate responsibilities: the Model stores data and business rules, the View handles what appears on the screen, and the Presenter manages the communication between the two.
In this structure, the View does not access the Model directly. The Model also does not know how the View looks or which UI system it uses. The entire flow is handled by the Presenter. For example, when the user clicks a button, the View only sends a “button clicked” event. The Presenter listens to this event, performs the necessary operation in the Model, and sends the result back to the View.
In Unity, this can be imagined through a simple coin counter. CoinView tells CoinPresenter that the button has been clicked. The Presenter increases the counter inside CoinModel and writes the new value back to the View. This way, game logic, data handling, and visual operations do not get mixed inside the UI code.
When is it used?
MVP is most useful when the UI starts to grow. If a project only has a small prototype with a single button, this structure may be unnecessary. However, if there are multiple inputs, different screen states, validation steps, or complex user flows, MVP makes the code easier to control.
It is also a good choice when you want to test UI logic. Since the Presenter can be written as a plain C# class, it can be tested without opening a Unity scene or depending on MonoBehaviour. You can use a mock View instead of the real one to check whether the Presenter works correctly.
It is also useful when the same game logic needs to be shown through different interfaces. For example, if you want to use the same system on a mobile UI, a console interface, and a different HUD design, the Model and Presenter can mostly stay the same; only the View changes.
MVP also helps when the team grows. A UI designer can work on the View while a programmer develops the Presenter and Model. As long as the interface between them stays stable, everyone can work on the same feature without constantly breaking each other's work.
Animation
Code
using UnityEngine;
namespace Patterns.Architectural.MVP
{
public class CoinScreen : MonoBehaviour
{
[SerializeField] private CoinView _coinView;
private CoinPresenter _presenter;
private void Start()
{
var model = new CoinModel(startCoins: 0);
_presenter = new CoinPresenter(model, _coinView);
}
private void OnDestroy()
{
_presenter?.Dispose();
}
}
}Advantages and Disadvantages
• Advantages:
- Testability improves because the Presenter can be tested without running Unity.
- Responsibilities stay clear between the View, Presenter, and Model.
- UI changes are easier because often only the View needs to be rewritten.
• Disadvantages:
- MVP adds more files and boilerplate, which can feel unnecessary in small projects.
- The Presenter can become too large if too much logic is placed in one class.
- Event management needs care, especially during scene transitions.
Tips
The Presenter should be kept as a plain C# class as much as possible. It does not need to inherit from MonoBehaviour. If Unity lifecycle methods such as Start, Update, or OnDestroy are needed, it is usually cleaner to manage them through the View.
The View should stay passive. Its job is to send button clicks as events and display the values coming from the Presenter. Decisions such as “when should the button be disabled?”, “is the value valid?”, or “which panel should open in this situation?” should not be made inside the View. They should be handled by the Presenter.
Event subscriptions should always be cleaned up. When the View is destroyed or the scene changes, event connections in the Presenter should be removed. This is one of the most commonly skipped details when using MVP in Unity, but it can cause serious problems later.
If the Presenter starts getting too large, the screen should be divided into smaller parts. For example, instead of using one large InventoryPresenter, using InventoryListPresenter and InventoryDetailPresenter can make the code easier to read.
UI information should not be placed inside the Model. The Model should not know about colors, fonts, animations, or panel states. It should only contain data and business rules. Everything related to visuals should stay in the View, while flow decisions should be managed by the Presenter.