Для начала разберемся, что такое 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/
Добавить комментарий