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

в 9:31, , рубрики: C#, 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 может следить так же за вьюшными ивенты, например коллезии или триггеры.

Автор: vildafaust

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js