Universal Unity MVP solution

996 Views Asked by At

I am looking for some sort of universal solution for implementing MVP in Unity. I've been working on a project before and guys had pretty nice solution but I don't remember exactly how it worked.

So I tried to recreate this as I remember and stuck realizing that I don't know how to connect everything up. Following my logic it should be something universal. Something like an asset, or package that you can just add to your project as it is and build your own classes on top of it so they fit in the pattern. I started from interfaces for View and Presenter. View is basically GameObject who works with all the UI or any visible part of your module.

IView

 public interface IView
    {
        public IPresenter Presenter { get; set; }

        public virtual void OnInit() { }
    }

IPresenter

public interface IPresenter
    {
        public IView View { get; set; }
        public Model.Model Model {get; set;}
    }

Then I start implementing the View class. It should inherit from MonoBehaviour in order to act as a Component on a GameObject and receive references to other objects in scene. On Init method is a perfect place to play the start animation for example.

View

 public class View : MonoBehaviour, IView
    {
        public IPresenter Presenter { get; set; }

        public void OnInit()
        {

        }
        private void Awake()
        {
            Presenter = new Presenter.Presenter(this);
        }
    }

Presenter do not need to inherit from the MonoBehaviour because it just holds logic and operates the data.

Presenter

 public class Presenter : IPresenter
    {
        public IView View {get; set;}
        public Model.Model Model { get; set; }

        public Presenter(IView view)
        {
            Model = new Model.Model();
            Model.Presenter = this;
            View = view;
            View.OnInit();
        }

    }

Model

 public class Model
    {
        public Presenter.Presenter Presenter { get; set; }
        public Model() { }
    }

At the moment my Model class is empty because I end up realizing that I don't know how to connect View to a Presenter. In fact I did connected all those classes, but for me it seems to be wrong that everything depends on a View as it is only one Unity-dependent class in this architecture. Probably I should have different class that creates instances of Model and Presenter and assigns them to each other. I don't know how to do it right.

Also i start using the namespaces in this project and for some reason I can't use just Presenter or just Model class. I have to use Presenter.Presenter or Model.Model instead. What am I doing wrong? It should be a common problem.

So If you have used something similar to it before tell me where is my general mistake that prevents me from completing this simple task. Maybe you already have done the solution I am looking for. Thanks for replies)

1

There are 1 best solutions below

1
On

I highly recomend you to take a look on Zenject This way you will have an Installer who will instantiate your Presenter and Model and inject each (and the View) in the required classes.

public interface IView
{
}

public interface IPresenter
{
}

public interface IModel
{
}

public class View : MonoBehaviour, IView
{
    [Inject] private readonly IPresenter _presenter;
}

public class Presenter : IPresenter
{
    [Inject] private readonly IView _view;
    [Inject] private readonly IModel _model;
}

public class Model: IModel
{
    [Inject] private readonly IPresenter _presenter;
}

public class CustomInstaller : MonoInstaller
{
    public override void InstallBindings()
    {
        Container.Bind<IModel>().To<Model>().AsSingle();
        Container.Bind<IView>().FromComponentInParents();
        Container.Bind<IPresenter>().To<Presenter>().AsSingle();
    }
}

(Note that I didn't test the code and I removed logic to make it simple and showing you the advantage of Zenject in your usecase)

About your namespace problem, to avoid Presenter.Presenter, you just have to use a using statement, like: using Presenter;