MVC в Unity или как упростить жизнь

от автора

Для начала разберемся, что такое MVC (Model View Controller)

Зачем же он нужен? Самый простой ответ — для постройки удобной и расширяемой архитектуры.

Стоит разобраться зачем нужно дробить взаимодействие на три разных класса. Во-первых разделение обязанностей, следую принципам SOLID. Во-вторых для простого взаимодействия с серверами для синхронизации данных.

Разберемся поподробнее об обязанностях на примере

PlayerView.cs — представляет собой в частности MonoBehaviour класс

using UnityEngine;  public class PlayerView : MonoBehaviour  {  }

PlayerModel.cs — представляет собой класс данных

public class PlayerModel {  }

PlayerController.cs — представляет собой класс связности между model и view

public class PlayerController {    private PlayerView _playerView;    private PlayerModel _playerModel     public PlayerController(PlayerView view, PlayerModel model)    {       _playerView = view;       _playerModel = model;    } }

Вот и весь паттерн.

А теперь разберемся зачем все это нужно.

PlayerView.cs добавляем, как компонент на наш Prefab игрока.

Остальные классы создаются в каком-либо управляющем классе. Создадим для примера управляющий класс.

Создадим пустой объект на сцене и навесим компонент GameManager

GameManager.cs

public class GameManager : MonoBehaviour {     public GameObject _playerPrefab;     private PlayerController _playerController;     private PlayerModel _playerModel;      public void Start(){         _playerModel = new PlayerModel();          var playerObject = Instantiate(_playerPrefab, Vector3.zero,Quaternion.identity);         var playerView = playerObject.GetComponent<Playerview>();          _playerController = new PlayerController(playerView, _playermodel)     } }

Отлично теперь на старте игры у нас будет создаваться Player. Но что дальше-то?

На самом деле далее это полет фантазии механик. Ну давайте для примера расширим Player model добавив здоровье.

PlayerModel.cs

public class PlayerModel {       public event Action Death;       public event Action<float> ChangedHealth;        private float _maxHp = 100;       private float _currentHp;        public PlayerModel(){           _currentHp = maxHp;       }        public void SetNewHealth(float damage)       {          _currentHp -= damage;          if(_currentHp > 0)               ChangedHealth?.Invoke(_currentHp);          else               Death?.Invoke();       } }

Теперь у нашего игрока появилось Health и два event на изменение здоровья и смерть. То есть Model — представляет сосредоточение всех данных игрока и решает что нужно делать при изменении каких-либо данных.

Теперь расширим Playercontroller, чтобы мы могли взаимодействовать с данными

PlayerController.cs

public class PlayerController {    private PlayerView _playerView;    private PlayerModel _playerModel     public PlayerController(PlayerView view, PlayerModel model)    {       _playerView = view;       _playerModel = model;    }     public void Enable()    {        _playerModel.Death += Death;        _playerModel.ChangedHealth += ChangeHealth;    }     private void ChangeHealth(float  health){        _playerView.Changehealth(health);    }     private void Death(){        _playerView.Death();        Disable();    }     public void Disable()    {        _playerModel.Death -= Death;        _playerModel.ChangedHealth -= ChangeHealth;    } }

Следовательно давайте расширим и PlayerView

PlayerView.cs

public class PlayerView : MonoBehaviour  {     public void Changehealth(float health)     {         //Уже любыми средствами отрисовывать визуальную часть         //это может как быть slideBar или просто Text      }      public void Death()     {         //Например можете проиграть анимацию смерти     } }

Следовательно мы получили крайне удобную архитектуру создание юнита (или любого другого объекта), который может расширяться любыми механиками. Нужна мана? Или передвижение? Добавьте в модель float mana, Vector3 position.

Какой должен быть вывод? Не мешать данные View (MonoBehaviour) с простыми просчетами.
Контроллер в нашем случае находится над уровнем PlayerView и PlayerModel и следит меняется ли что-либо там и реагирует на изменения. При том PlayerController может следить так же за вьюшными ивенты, например коллезии или триггеры.


ссылка на оригинал статьи https://habr.com/ru/post/481618/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *