Маленькое уточнение! В классической модели MVC от Трюгве Реенскауга контроллер НЕ ВЗАИМОДЕЙСТВУЕТ с видом. Обновление вида происходит СТРОГО через модель. В коде на видео у меня контроллер дёргал вид, когда показывал текст об успешной линии. Я это исправил, в гите теперь всё правильно. Кому интересно, почему так, можете ознакомиться с научной работой Трюгве Реенскауга folk.universitetetioslo.no/trygver/2003/javazone-jaoo/MVC_pattern.pdf (14 страница - две UML диаграммы P11 в правом углу. По ним видно что именно модель шлёт сигнал виду) Такая схема кажется довольно странной, вы не обязаны ей следовать, и можете обновлять вид например через контроллер. Но именно модель обновляющая вид это исторический канон, хотя опять же скажу что придерживаться канонов не обязательно. Также хочется добавить что в MVP и MVVM модель уже не обновляла вид. В MVP появился Passive View который убирал связь модели и вида, в MVVM вообще все перекрутили на датабиндинг
За такую подачу материала просто необходимо поставить лайк и написать коммент. Посмотрел несколько видео про паттерны. Продолжайте в том же духе, такие видео просто необходимы новичкам.
Спасибо за видос про MVC, жду последующие разборы про остальные паттерны из этого семейства. Хотелось бы в дальнейшем еще увидеть видос про пул объектов
Хорошее видео! Автор крепко пишет код и объясняет. Хотелось бы услышать про MVP - Super view (или active... крч противоположный Passive) и MVVM - зачем такое мучение с биндингами и прочее
Спасибо) как раз начал сегодня формировать материал про MVP, думал superviser view и passive vies скипнуть, но раз есть такой запрос - расскажу. Хотя там в две строчки всё описывается)
Очень редко пишу комментарии, но вижу, что пока мало просмотров и подписчиков. Подписался и пролайкую видосы. Канал топ - закрывает бреш в нашем ру-язычном геймдев комьюнити. Главное не бросай)
Имхо модель с барменом, в том виде, в каком она представлена - не слишком удачная... Ибо клиент может сразу взять меню и протянуть ее бармену и бармен будет взаимодействовать уже с меню (пытаясь понять, во что клиент тыкнул пальцем со словами "дайте две"!). т.е. стрелочки от Вью до Контроллера будут в обе стороны. Плюс в обе стороны будут стрелочки от Холодоса до Бармена. В итоге выстроится цепочка Клинт-Бармен-Холодос-Бармен-клиент... т.к. меню может быть в принципе не нужно. Так же клиент может сразу подойти к холодильнику и на глазах у бармена достать нужное ему пивко, т.к. у него, скажем, уже оплачены напитки на вечер. т.е. клиент работает непосредственно с моделью, минуя контроллер и вью. Что в коре противоречит концепции мвц. В примере с баром Вью должно быть не меню, а непосредственно пивко в стакане. А за место холодоса можно взять бочку с пивным краном. Тогда трио Бармен-Бочка-Пиво, хоть как то похоже на мвц в чистом виде... А то, что дает пример автор в видео, как раз таки и порождает те самые тысячи прочтений МВЦ с десятками разнообразных стрелочек в разные стороны, которые мы часто видим в интернете.
Во-первых, на второй минуте я объяснил почему стрелочки на разных сайтах отображаются по-разному. Во-вторых, имхо, модель бармен-бочка-пиво ещё хуже моей и вот почему. В MVC есть три слоя : данные, логика и представление данных. Я предлагаю на примерах пробежаться по этим слоям и посмотреть что лучше подходит. Первый слой - данные или же модель. Модель это слой отвечающий за состояние, уведомляющий вид о своём изменении. Мой умный холодильник(а я его так описал) под это подходит - вытащили пивко - бахнули пуш на онлайн меню. В вашем примере может ли пиво, то есть хмельная жижа уведомить бармена что состояние изменилось? Нет. Отмечу, что именно пиво по каноничному MVC должна сигналить бармену. Если бармен(вид) следит за состоянием пива(модель) то это стрелочка в обратную сторону повёрнута что не канон. Далее - контроллер - логика, оно же действие или работа над данными. Задача контроллера - обрабатывать пользовательский ввод и изменять состояние модели. В моей схеме логика это бармен. Бармен принимает заказ пользователя и достаёт пивко, то есть обрабатывает пользовательский ввод и изменяет состояние холодильника. В вашей схеме - бочка с краном является прослойкой между состоянием(пивом) и видом(барменом). В вашей схеме кран обрабатывает пользовательский ввод? Вроде бы да, и состояние изменяет, вот только вопрос - а кто краник то дёргает? Посетитель? Тогда это странный бар, приходит клиент, бармен ему говорит вот пивко, хочешь наливай и пользователь сам себе льёт. Какая-то пивнуха самообслуживания получается. Или краник дёргает бармен? Тогда почему тот, кто занимается видом, занимается ещё и логикой? Ну и наконец - вид, оно же представление состояния. Задача вида - отображать состояние данных пользователю в той или иной форме и получать уведомления от модели об изменении. Меню, при условии что оно показывает какое бухлишко есть а какого нет - под это описание подходит. Но это я уже спрашивал - как бармен(вид) узнаёт об изменении состояния пива? При условии что его должны уведомить а не выяснить это сам? Отвечая на вопрос "а что если пользователь напрямую полезет в холодос" - хочу спросить - а вы часто в баре или ресторане проходите на кухню и достаёте жратву из секции где сидят повара? Или часто в баре вы заходите за барную стойку и сами берёте алкоголь и наливаете себе в стакан. Что в жизни что в коде это нарушение заданного контракта и соглашений. Я могу также спросить - "А что если бармен вырвет кран и будет из дырки наливать пивко?" Структура не изменится, стакан наполнить получится, а один из трёх компонентов пропал. Вопрос такой смысла не имеет. Ну и под финалочку, да, в описании есть небольшой косяк ибо в каноничном MVC контроллер не взаимодействует с видом. Я написал об этой коммент в закрепе под этим видео. И потому стрелочки "консультирует пользователя по меню" не должно быть. Тут я накосячил, каюсь. И раз этой стрелочки нет можно поискать другую аналогию, но пока её я не придумал. Если придумаете - возможно в версии 2.0 я приведу именно её
Если уж вы хотите ваш пример сделать по MVC то тогда это будет выглядеть так. Есть бар где пользователи наливают себе пивко из бочек, а бармены их только консультируют какие бочки полны а какие нет. Бочка с пивом(в которой есть датчик полноты) - это модель, и она шлёт пуши бармену(наверное тоже надо кибер имплант как приёмник бармену пришить, хотя обычная гарнитура сойдет). Бармен это вид. А краник это контроллер. Тогда похоже на правду
Я вот тут пытаюсь понять: модель, вью и контроллер является одним модулем. В рамках разработки на Unity можно ли это отнести к одному префабу, к примеру, отдельного скрина в главном меню? (Настройки как отдельный префаб скрина со своей моделью, вью и контроллером, главное меню и и д) И еще вопрос - можно ли комбинировать несколько архитектур в одном проекте? К примеру с событийно-ориентированной архитектурой?
Обычно в unity я если реализую mv* паттерны, я разделяю их на три скрипта. На префабе висит только вид, модель и контроллер имеют ссылки на вид но все же существуют отдельно(пусть и не как монобех объекты) Насчёт комбинирования, я считаю самое важное, чтобы проект было комфортно поддерживать и расширять. В моих проектах часто есть основная архитектура, но есть локальные решения типа mvc, unirx и тд Так что мой ответ такой: совмещать можно, если проект не превращается в неподдерживаемое и неудобное нечто)
Здравствуйте, Сергей! Спасибо за прекрасные обучающие материалы, очень много полезного для себя почерпнул. Хотел бы задать такой вопрос: как Вы считаете, может ли MVC существовать без какого-либо компонента, например Model (когда не нужно что-либо хранить) или View (когда не нужно что-либо отображать)? или тогда это уже не MVC, а что-то другое? Например: я реализовал логику сохранения данных (позиция игрока, собранные предметы, пройденные квесты и т.д.) в игре посредством создания GameData- Model (в модели хранятся непосредственно данные и в конструкторе задаются данные по-умолчанию) & Controller (отвечает за логику сохранения / загрузки данных, в том числе на основе событий). View нет, т.к. нет необходимости что-то отображать в данной связке.
Здравствуйте! Да, такое возможно, но это уже не паттерн MVC. Это просто разделение кода на разные слои В этом ничего плохого нет. Я сам часто для UI разбиваю код только на два слоя: данные и вид. Пока на виде(каком-нибудь окошке) пара кнопок и никакой сложной логики - Controller или Presenter я не создаю
Слишком холиварная тема) Во первых, многие серьезные программисты на юнити считают, что не нужно приносить MV паттерны в юнити, так как здесь принято использовать компонентный подход к разработке, который отлично работает. Но некоторые не менее серьезные программисты считают, что MVC хорош в юнити, но многие его понимают не верно и его нужно уметь готовить. Так например, люди думают, что модель - это просто набор данных без логики (то есть тупо совокупность публичных полей), а все доменная логика содержится в контроллерах, но это так называемый Simple или Anemic domain model, который в DDD считают не очень хорошей практикой, в терминах DDD модель - это совокупность приватных полей и методов, которые их обрабатывают, то есть ООП здорового человека. А контроллер в таком случае становится очень тонким, он не содержит доменной логики приложения и играет лишь роль некой прослойки, для более гибкой разработки, в простых проектах, можно даже не делать контроллеров. Еще одно не понимание связанное с MVC в юнити, это то, что за view принимают лишь графический интерфейс, хотя по факту view - это все что отображается на экране, то есть game object'ы, на которых есть модели, спрайты и аниматоры, это тоже view. В таком случае у нас даже может быть модель, независимая от движка, и перенос проекта на другой движок сводится лишь к написанию новых view'шек для отображения объектов на этом движке, но такие вещи это уже оверинжинеринг, как по мне. Такой MVC вполне уже можно использовать в юнити, но нужно ли? Посмотрите на другие движки, типа Unreal, Godot и других, компонентный подход там вполне справляется. Да в юнити у нас убогий компонентный подход, без конструкторов даже и невозможностью нормально резолвить сервисы из коробки (привет FindObjectOfType() и синглтоны). Но DI частично это проблему решает.
Хорошее замечание! По моему опыту действительно чистый mvc используется редко, чаще используется MVP или MVVM. Но также в юнити вполне неплохо прижилась идея отделения данных от логики и вида. Писал клоны Coin master-a и для тех же слот машин такой подход заходит на ура :)
Хотелось бы услышать твое мнение по поводу того как правильно организовать взаимосвязь между Игрок, Уровень, Модули, UI, GameManager. Иметь какуето строгую типизацию и синглетон, либо же делать это все самостоятельными сущностями
Зависит от размера проекта и его особенностей. Я лично не могу сказать что нашёл идеальную архитектуру и баланс, но мне кажется самое сбалансированное это что-то типа сервис локатора + статической сигнальной шины(статический класс который рассылает ивенты и классы взаимодействуют друг с другом через неё) Я сейчас добью MVVM и попробую запустить новую рубрику: буду писать гиперказуалки и внимание уделять именно архитектуре и паттернам на практике. Пока не знаю что из этого выйдет, как много это займёт времени, но может после публикации того видео моё мнение изменится)
Спасибо за твои видео! У меня есть вопрос, Если мы например делаем игрока по паттерну mvc, m - PlayerModel имеет поля и методы по обработке этих полей, c - PlayerController получает Input-ы и связывает m и v, v - ViewPlayer отвечает за анимации игрока и все с этим связанное, то куда нам запихнуть логику передвижения? Если ее запихнуть в PlayerModel или PlayerController, то им придется наследовать Monobehaviour, чтобы реализовать это. В ViewPlayer мне кажется засовывать не очень хорошей идеей, тк это нарушит srp. Как мне кажется лучше всего передвижение сделать отдельным компонентом (пусть это будет MovementController) , но тогда не понятно, как должно происходить его взаимодействие с остальными элементами и где должны храниться данные связанные с перемещением (например float _speed, должен быть в PlayerModel или MovementController)? Второе, что мне не понятно, как все это настраивать из инспектора, все должно быть в MainScripts? Тогда он сильно разрастется и будет не удобно. + всегда удобно тестить игру, когда напрямую из инспектора можешь менять хп, скорость и тд. Или MVC паттерн плохо подходит для таких вещей? Тогда какой software design pattern нужно использовать? P.s Я скачал проект с гат-хаба и там небольшая ошибочка: когда Is 3 Line Logic == true, работает CentralLineController, а не AllLinesController. те Controller-а поменяны местами. P.p.s Я посмотрел ролик про mvp и почти тоже самое можно сказать и про него, хотя с ним и проще, тк думаю можно OnCollision-ы засунуть в View, тк это своеобразный Input.
Привет! Ты задал хороший вопрос. Куда нам запихнуть логику передвижения? Согласно концепции MVC логика передвижения должна находиться только в Controller-е. В идеале эта логика передвижения наоборот не должна зависеть от монобеха, а должна полностью считаться на чистом C# без всяких OnCollision/OnTrigger и тд. Так MVC будет чистым, и ты сможешь свою логику передвижения легко перекинуть на какую нибудь джаву или быть готовым к тому что вид или модель у тебя будут написаны на другом языке. На практике конечно никто на чистом MVC никто игры не пишет именно потому что не очень охота ограничивать себя от функционала юнити: физики, коллайдеров и триггеров. Поэтому да, придётся делать контроллер монобехом и счиитать управление там. На счёт "удобно тестить игру, когда напрямую из инспектора можешь менять хп, скорость и тд" - ты можешь создать отдельный класс который объединяет Model, View и Controller и в него прокинуть твои параметры. Тем самым у тебя будет специальный скрипт в котором лежат все с MVC связанное и уже ЭТОТ скрипт ты будешь добавлять в MainScript. Я эту механику ещё не обкатал, хочу во второй игре которую я напишу для рубрики "Паттерны на практике" прикрутить, но мне кажется она зайдет. На счёт MainScript - да, должен быть рутовый какой-то скрипт игры, чаще всего для этого используют паттерн EntryPoint или тот же DI-Container. По Entry Point у меня последнее видео, можно посмотреть как это приблизительно делается. Да, он будет распухать, но всё равно будет трудно построить архитектуру игры без рутового скрипта в котором всё инициализируется. Чистый MVC с моей точки зрения для нас юнитологов подходит не всегда. НО, идея разделять архитектуру так чтобы модель была отдельно, логика отдельно, вид отдельно - очень хорошая и полезная. Есть жанры которые от разделения архитектуры на три слоя(данные логика и вид) сильно выигрывают: те же match3, слот машины или сетевые игры. "когда Is 3 Line Logic == true, работает CentralLineController" - да, поправлю, плохой нейминг, я имел ввиду не Is3Line а Is3SlotOnly
мне кажется ссылка модели на вью лишняя, там скорее должен быть ивент, на который подписан контроллер (который этот вью и заставит рисовать по факту), что полностью убирает прямые связи между вью и моделью (в чём собственно и прикол паттерна вроде как)
Как я и сообщал в видео, стрелочки и связи между тремя компонентами вы можете проставить как угодно, в зависимости от потребностей и предпочтений Но канонично модель ссылается на вью. Как я понял эта архитектура была придумана до ивентов, и потому именно модель обновляла вид. Но опять же никто не заставляет следовать ортодоксальной архитектуре равно как и никто не запрещает использовать ивенты
В модели не должно быть когда отвечающего за логику. Логикой занимается контроллер. Если мы один контроллер заменим на другой, что в модели новый метод Spin писать? В модели только сеттеры и ссылка на вид и команда на отрисовку нового состояния модели
@@sergeykazantsev1655 модель по сути чистая бизнес логика, какой смысл переносить её в контроллер? Какой смысл модели знать о наличии вью? Контроллер это внешней класс, который отвечает за связанность модели, вью и юзер-интерфейсов, в то время как модель и вью выполняют свои функции "по приказу" конроллера, но не подозревая о нём, контроллер же следит за моделью либо самостоятельно, либо реагирую на ивенты.
Спасибо за видео. Получается на UML Controller не должен иметь связи с View и Controller не должен в себе иметь переменной View совсем? То есть Сontroller -> Model -> View получается? 1. Контроллер получает нажатие клавиши, берёт данные с Модели и их изменяет; 2. Модель получает\обновляет данные и отправляет их на Вид? 3. Вид изменять визуал игры; Потому что из кода на github и текста ниже получается так, нет? И еще вопрос: Я хочу начать вести мини блог на LinkendIn и написать о MVC, как я его разобрал и понял. Могу ли я ссылаться на это видео? Ссылку на видео я конечно же прикреплю.
Да, получается так. По крайней мере в каноничном представленном MVC схема именно такая. Контроллер не имеет доступа напрямую к View, контроллер изменяет лишь модель. Опять же уточню, что этой схеме не обязательно следовать, этой схеме много лет и она не совсем адекватно ложится на современный геймдев, но это именно та схема которую представил автор MVC. Да, пожалуйста, можете на меня ссылаться 🙂 Если какие-то ребята захотят подискутировать и поспорить, пусть пишут мне в комментарии, или в личку в тг, вежливую и нетоксичную конструктивную дискуссию я всегда приветствую. И ссылку на линкедин тогда тоже попрошу, я там тоже есть бываю хоть и не часто :)
Лайк конечно. Но что-то факт того, что модель дергает вью напрямую без контроллера меня очень удивил. То есть, если мы меняем вью, нам надо ссылку на него поменять и в контроллере и в моделе? Что-то здесь не так...
Абсолютно согласен что тот факт, что модель дёргает вью напрямую без контроллера выглядит очень странно. Но так указано в научной работе как Трюгве Реенскауга folk.universitetetioslo.no/trygver/2003/javazone-jaoo/MVC_pattern.pdf (14 страница - две UML диаграммы P11 в правом углу. По ним видно что именно модель шлёт сигнал виду) так и в той же википедии(хотя конечно вики так себе авторитет) ru.wikipedia.org/wiki/Model-View-Controller (model Updates View) В защиту могу сказать что это на этапе становления эту странность в MVP и MVVM пофиксили. В MVP появился Passive View который убирал связь модели и вида, в MVVM вообще все перекрутили на датабиндинг На некоторых статьях по MVC эту проблему так же фиксят как вы рекомендуете, то есть через Controller. Если попробуете загуглить MVC в картинках увидите и тот и другой вариант. Но вариант в видео каноничный, хоть и не значит что строго обязательно следовать ему. Главное чтобы вы решали ваши задачи и вам было удобно И да, ссылку надо прокидывать на него в двух местах, но только наверху в условном MainScript, что не такая уж и проблема
@@sergeykazantsev1655 Слушай, я посмотрел эти диаграммы и я их понимаю так что в контроллере нет ссылки на вью. Контроллер получает команду от пользователя, меняет модель, а модель уже меняет вью. Контроллер со вью вообще никак не связан.
Блин, точняк. А я в коде получается часть логики считаю в контроллере и передаю на вид(логика победы) а часть логики передаю с модели на вид - результат вращения. В общем тогда пример не самый удачный получился :D Надо будет переписать код примера чтобы контроллер не взаимодействовал с вью
Маленькое уточнение! В классической модели MVC от Трюгве Реенскауга контроллер НЕ ВЗАИМОДЕЙСТВУЕТ с видом. Обновление вида происходит СТРОГО через модель. В коде на видео у меня контроллер дёргал вид, когда показывал текст об успешной линии. Я это исправил, в гите теперь всё правильно.
Кому интересно, почему так, можете ознакомиться с научной работой Трюгве Реенскауга folk.universitetetioslo.no/trygver/2003/javazone-jaoo/MVC_pattern.pdf
(14 страница - две UML диаграммы P11 в правом углу. По ним видно что именно модель шлёт сигнал виду)
Такая схема кажется довольно странной, вы не обязаны ей следовать, и можете обновлять вид например через контроллер. Но именно модель обновляющая вид это исторический канон, хотя опять же скажу что придерживаться канонов не обязательно.
Также хочется добавить что в MVP и MVVM модель уже не обновляла вид. В MVP появился Passive View который убирал связь модели и вида, в MVVM вообще все перекрутили на датабиндинг
Кстати ещё хотел отметить юмор, мне очень заходит и помогает в лёгкой форме всё осваивать
Спасибо, стараюсь вставлять смешнявочки, там где это не отвлечет внимание от важного материала)
За такую подачу материала просто необходимо поставить лайк и написать коммент. Посмотрел несколько видео про паттерны. Продолжайте в том же духе, такие видео просто необходимы новичкам.
Спасибо за видос про MVC, жду последующие разборы про остальные паттерны из этого семейства. Хотелось бы в дальнейшем еще увидеть видос про пул объектов
Как всегда, всё замечательно объяснил и разложил по полочкам, с отличными примерами. Спасибо!
Это лучшее и самое приятное объяснение что я видел на ютубе, подписался :)
Тонна благодарностей! Ты большой молодец! Подготовка - понимание - подача! Стакан пенного эля этому господину!!
Можно задонатить на кофе и шаурму :D но и так приятно)
@@sergeykazantsev1655 как только работу найду - закину. Пока только словами, сорян)
@@РоманВоронин-н7и нашли работу?
Хорошее видео! Автор крепко пишет код и объясняет. Хотелось бы услышать про MVP - Super view (или active... крч противоположный Passive) и MVVM - зачем такое мучение с биндингами и прочее
Спасибо) как раз начал сегодня формировать материал про MVP, думал superviser view и passive vies скипнуть, но раз есть такой запрос - расскажу. Хотя там в две строчки всё описывается)
@@sergeykazantsev1655 буду ждать)
Красавчик!
Интересная тема, жду следующие видео про mv*
Видео просто пушка. Спасибо
Подача материала просто шикарная!!!
Топчик. Выросло качество видео и звук по сравнению с прошлыми видео. Простым языком о сложном.
Спасибо за видео, желаю набрать скорее побольше подписчиков. Такой качественный контент.
Лучшее видео по MVC на русском, красавчик
Все понятно. Спасибо. Ты крут.
Очень редко пишу комментарии, но вижу, что пока мало просмотров и подписчиков. Подписался и пролайкую видосы. Канал топ - закрывает бреш в нашем ру-язычном геймдев комьюнити. Главное не бросай)
Да, было интересно , спасибо
канал топ. поклон тебе добрый человек
Спасибо за информацию. Стало чуть яснее.
Имхо модель с барменом, в том виде, в каком она представлена - не слишком удачная...
Ибо клиент может сразу взять меню и протянуть ее бармену и бармен будет взаимодействовать уже с меню (пытаясь понять, во что клиент тыкнул пальцем со словами "дайте две"!). т.е. стрелочки от Вью до Контроллера будут в обе стороны. Плюс в обе стороны будут стрелочки от Холодоса до Бармена. В итоге выстроится цепочка Клинт-Бармен-Холодос-Бармен-клиент... т.к. меню может быть в принципе не нужно.
Так же клиент может сразу подойти к холодильнику и на глазах у бармена достать нужное ему пивко, т.к. у него, скажем, уже оплачены напитки на вечер. т.е. клиент работает непосредственно с моделью, минуя контроллер и вью. Что в коре противоречит концепции мвц.
В примере с баром Вью должно быть не меню, а непосредственно пивко в стакане. А за место холодоса можно взять бочку с пивным краном. Тогда трио Бармен-Бочка-Пиво, хоть как то похоже на мвц в чистом виде...
А то, что дает пример автор в видео, как раз таки и порождает те самые тысячи прочтений МВЦ с десятками разнообразных стрелочек в разные стороны, которые мы часто видим в интернете.
Во-первых, на второй минуте я объяснил почему стрелочки на разных сайтах отображаются по-разному.
Во-вторых, имхо, модель бармен-бочка-пиво ещё хуже моей и вот почему. В MVC есть три слоя : данные, логика и представление данных. Я предлагаю на примерах пробежаться по этим слоям и посмотреть что лучше подходит.
Первый слой - данные или же модель. Модель это слой отвечающий за состояние, уведомляющий вид о своём изменении. Мой умный холодильник(а я его так описал) под это подходит - вытащили пивко - бахнули пуш на онлайн меню. В вашем примере может ли пиво, то есть хмельная жижа уведомить бармена что состояние изменилось? Нет. Отмечу, что именно пиво по каноничному MVC должна сигналить бармену. Если бармен(вид) следит за состоянием пива(модель) то это стрелочка в обратную сторону повёрнута что не канон.
Далее - контроллер - логика, оно же действие или работа над данными. Задача контроллера - обрабатывать пользовательский ввод и изменять состояние модели. В моей схеме логика это бармен. Бармен принимает заказ пользователя и достаёт пивко, то есть обрабатывает пользовательский ввод и изменяет состояние холодильника.
В вашей схеме - бочка с краном является прослойкой между состоянием(пивом) и видом(барменом). В вашей схеме кран обрабатывает пользовательский ввод? Вроде бы да, и состояние изменяет, вот только вопрос - а кто краник то дёргает? Посетитель? Тогда это странный бар, приходит клиент, бармен ему говорит вот пивко, хочешь наливай и пользователь сам себе льёт. Какая-то пивнуха самообслуживания получается. Или краник дёргает бармен? Тогда почему тот, кто занимается видом, занимается ещё и логикой?
Ну и наконец - вид, оно же представление состояния. Задача вида - отображать состояние данных пользователю в той или иной форме и получать уведомления от модели об изменении. Меню, при условии что оно показывает какое бухлишко есть а какого нет - под это описание подходит. Но это я уже спрашивал - как бармен(вид) узнаёт об изменении состояния пива? При условии что его должны уведомить а не выяснить это сам?
Отвечая на вопрос "а что если пользователь напрямую полезет в холодос" - хочу спросить - а вы часто в баре или ресторане проходите на кухню и достаёте жратву из секции где сидят повара? Или часто в баре вы заходите за барную стойку и сами берёте алкоголь и наливаете себе в стакан. Что в жизни что в коде это нарушение заданного контракта и соглашений.
Я могу также спросить - "А что если бармен вырвет кран и будет из дырки наливать пивко?" Структура не изменится, стакан наполнить получится, а один из трёх компонентов пропал. Вопрос такой смысла не имеет.
Ну и под финалочку, да, в описании есть небольшой косяк ибо в каноничном MVC контроллер не взаимодействует с видом. Я написал об этой коммент в закрепе под этим видео. И потому стрелочки "консультирует пользователя по меню" не должно быть. Тут я накосячил, каюсь. И раз этой стрелочки нет можно поискать другую аналогию, но пока её я не придумал. Если придумаете - возможно в версии 2.0 я приведу именно её
Если уж вы хотите ваш пример сделать по MVC то тогда это будет выглядеть так. Есть бар где пользователи наливают себе пивко из бочек, а бармены их только консультируют какие бочки полны а какие нет. Бочка с пивом(в которой есть датчик полноты) - это модель, и она шлёт пуши бармену(наверное тоже надо кибер имплант как приёмник бармену пришить, хотя обычная гарнитура сойдет). Бармен это вид. А краник это контроллер. Тогда похоже на правду
Я вот тут пытаюсь понять: модель, вью и контроллер является одним модулем. В рамках разработки на Unity можно ли это отнести к одному префабу, к примеру, отдельного скрина в главном меню? (Настройки как отдельный префаб скрина со своей моделью, вью и контроллером, главное меню и и д) И еще вопрос - можно ли комбинировать несколько архитектур в одном проекте? К примеру с событийно-ориентированной архитектурой?
Обычно в unity я если реализую mv* паттерны, я разделяю их на три скрипта. На префабе висит только вид, модель и контроллер имеют ссылки на вид но все же существуют отдельно(пусть и не как монобех объекты)
Насчёт комбинирования, я считаю самое важное, чтобы проект было комфортно поддерживать и расширять. В моих проектах часто есть основная архитектура, но есть локальные решения типа mvc, unirx и тд
Так что мой ответ такой: совмещать можно, если проект не превращается в неподдерживаемое и неудобное нечто)
Здравствуйте, Сергей!
Спасибо за прекрасные обучающие материалы, очень много полезного для себя почерпнул.
Хотел бы задать такой вопрос: как Вы считаете, может ли MVC существовать без какого-либо компонента, например Model (когда не нужно что-либо хранить) или View (когда не нужно что-либо отображать)? или тогда это уже не MVC, а что-то другое?
Например: я реализовал логику сохранения данных (позиция игрока, собранные предметы, пройденные квесты и т.д.) в игре посредством создания GameData- Model (в модели хранятся непосредственно данные и в конструкторе задаются данные по-умолчанию) & Controller (отвечает за логику сохранения / загрузки данных, в том числе на основе событий). View нет, т.к. нет необходимости что-то отображать в данной связке.
Здравствуйте! Да, такое возможно, но это уже не паттерн MVC. Это просто разделение кода на разные слои
В этом ничего плохого нет. Я сам часто для UI разбиваю код только на два слоя: данные и вид. Пока на виде(каком-нибудь окошке) пара кнопок и никакой сложной логики - Controller или Presenter я не создаю
Слишком холиварная тема)
Во первых, многие серьезные программисты на юнити считают, что не нужно приносить MV паттерны в юнити, так как здесь принято использовать компонентный подход к разработке, который отлично работает.
Но некоторые не менее серьезные программисты считают, что MVC хорош в юнити, но многие его понимают не верно и его нужно уметь готовить. Так например, люди думают, что модель - это просто набор данных без логики (то есть тупо совокупность публичных полей), а все доменная логика содержится в контроллерах, но это так называемый Simple или Anemic domain model, который в DDD считают не очень хорошей практикой, в терминах DDD модель - это совокупность приватных полей и методов, которые их обрабатывают, то есть ООП здорового человека. А контроллер в таком случае становится очень тонким, он не содержит доменной логики приложения и играет лишь роль некой прослойки, для более гибкой разработки, в простых проектах, можно даже не делать контроллеров.
Еще одно не понимание связанное с MVC в юнити, это то, что за view принимают лишь графический интерфейс, хотя по факту view - это все что отображается на экране, то есть game object'ы, на которых есть модели, спрайты и аниматоры, это тоже view. В таком случае у нас даже может быть модель, независимая от движка, и перенос проекта на другой движок сводится лишь к написанию новых view'шек для отображения объектов на этом движке, но такие вещи это уже оверинжинеринг, как по мне.
Такой MVC вполне уже можно использовать в юнити, но нужно ли? Посмотрите на другие движки, типа Unreal, Godot и других, компонентный подход там вполне справляется. Да в юнити у нас убогий компонентный подход, без конструкторов даже и невозможностью нормально резолвить сервисы из коробки (привет FindObjectOfType() и синглтоны). Но DI частично это проблему решает.
Хорошее замечание! По моему опыту действительно чистый mvc используется редко, чаще используется MVP или MVVM. Но также в юнити вполне неплохо прижилась идея отделения данных от логики и вида. Писал клоны Coin master-a и для тех же слот машин такой подход заходит на ура :)
Так вот почему, когда я разрабатывал свою первую игру и постоянно вставал вопрос, мол, где главную логику реализовывать в модели или в контроллере.
Хотелось бы услышать твое мнение по поводу того как правильно организовать взаимосвязь между Игрок, Уровень, Модули, UI, GameManager. Иметь какуето строгую типизацию и синглетон, либо же делать это все самостоятельными сущностями
Зависит от размера проекта и его особенностей. Я лично не могу сказать что нашёл идеальную архитектуру и баланс, но мне кажется самое сбалансированное это что-то типа сервис локатора + статической сигнальной шины(статический класс который рассылает ивенты и классы взаимодействуют друг с другом через неё)
Я сейчас добью MVVM и попробую запустить новую рубрику: буду писать гиперказуалки и внимание уделять именно архитектуре и паттернам на практике. Пока не знаю что из этого выйдет, как много это займёт времени, но может после публикации того видео моё мнение изменится)
@@sergeykazantsev1655 Ооо, это интересно) Привет от мидкор и гибрид проектов :D
Спасибо за твои видео!
У меня есть вопрос, Если мы например делаем игрока по паттерну mvc, m - PlayerModel имеет поля и методы по обработке этих полей, c - PlayerController получает Input-ы и связывает m и v, v - ViewPlayer отвечает за анимации игрока и все с этим связанное, то куда нам запихнуть логику передвижения? Если ее запихнуть в PlayerModel или PlayerController, то им придется наследовать Monobehaviour, чтобы реализовать это. В ViewPlayer мне кажется засовывать не очень хорошей идеей, тк это нарушит srp. Как мне кажется лучше всего передвижение сделать отдельным компонентом (пусть это будет MovementController) , но тогда не понятно, как должно происходить его взаимодействие с остальными элементами и где должны храниться данные связанные с перемещением (например float _speed, должен быть в PlayerModel или MovementController)?
Второе, что мне не понятно, как все это настраивать из инспектора, все должно быть в MainScripts? Тогда он сильно разрастется и будет не удобно. + всегда удобно тестить игру, когда напрямую из инспектора можешь менять хп, скорость и тд.
Или MVC паттерн плохо подходит для таких вещей? Тогда какой software design pattern нужно использовать?
P.s Я скачал проект с гат-хаба и там небольшая ошибочка: когда Is 3 Line Logic == true, работает CentralLineController, а не AllLinesController. те Controller-а поменяны местами.
P.p.s Я посмотрел ролик про mvp и почти тоже самое можно сказать и про него, хотя с ним и проще, тк думаю можно OnCollision-ы засунуть в View, тк это своеобразный Input.
Привет! Ты задал хороший вопрос.
Куда нам запихнуть логику передвижения?
Согласно концепции MVC логика передвижения должна находиться только в Controller-е. В идеале эта логика передвижения наоборот не должна зависеть от монобеха, а должна полностью считаться на чистом C# без всяких OnCollision/OnTrigger и тд. Так MVC будет чистым, и ты сможешь свою логику передвижения легко перекинуть на какую нибудь джаву или быть готовым к тому что вид или модель у тебя будут написаны на другом языке.
На практике конечно никто на чистом MVC никто игры не пишет именно потому что не очень охота ограничивать себя от функционала юнити: физики, коллайдеров и триггеров. Поэтому да, придётся делать контроллер монобехом и счиитать управление там.
На счёт "удобно тестить игру, когда напрямую из инспектора можешь менять хп, скорость и тд" - ты можешь создать отдельный класс который объединяет Model, View и Controller и в него прокинуть твои параметры. Тем самым у тебя будет специальный скрипт в котором лежат все с MVC связанное и уже ЭТОТ скрипт ты будешь добавлять в MainScript. Я эту механику ещё не обкатал, хочу во второй игре которую я напишу для рубрики "Паттерны на практике" прикрутить, но мне кажется она зайдет.
На счёт MainScript - да, должен быть рутовый какой-то скрипт игры, чаще всего для этого используют паттерн EntryPoint или тот же DI-Container. По Entry Point у меня последнее видео, можно посмотреть как это приблизительно делается. Да, он будет распухать, но всё равно будет трудно построить архитектуру игры без рутового скрипта в котором всё инициализируется.
Чистый MVC с моей точки зрения для нас юнитологов подходит не всегда. НО, идея разделять архитектуру так чтобы модель была отдельно, логика отдельно, вид отдельно - очень хорошая и полезная. Есть жанры которые от разделения архитектуры на три слоя(данные логика и вид) сильно выигрывают: те же match3, слот машины или сетевые игры.
"когда Is 3 Line Logic == true, работает CentralLineController" - да, поправлю, плохой нейминг, я имел ввиду не Is3Line а Is3SlotOnly
@@sergeykazantsev1655 огромное спасибо
мне кажется ссылка модели на вью лишняя, там скорее должен быть ивент, на который подписан контроллер (который этот вью и заставит рисовать по факту), что полностью убирает прямые связи между вью и моделью (в чём собственно и прикол паттерна вроде как)
Как я и сообщал в видео, стрелочки и связи между тремя компонентами вы можете проставить как угодно, в зависимости от потребностей и предпочтений
Но канонично модель ссылается на вью. Как я понял эта архитектура была придумана до ивентов, и потому именно модель обновляла вид.
Но опять же никто не заставляет следовать ортодоксальной архитектуре равно как и никто не запрещает использовать ивенты
да и метод "Spin" в примере по-идее должен находится в моделе, контроллер может его разве что вызывать
В модели не должно быть когда отвечающего за логику. Логикой занимается контроллер. Если мы один контроллер заменим на другой, что в модели новый метод Spin писать?
В модели только сеттеры и ссылка на вид и команда на отрисовку нового состояния модели
@@sergeykazantsev1655 модель по сути чистая бизнес логика, какой смысл переносить её в контроллер? Какой смысл модели знать о наличии вью? Контроллер это внешней класс, который отвечает за связанность модели, вью и юзер-интерфейсов, в то время как модель и вью выполняют свои функции "по приказу" конроллера, но не подозревая о нём, контроллер же следит за моделью либо самостоятельно, либо реагирую на ивенты.
Спасибо за видео.
Получается на UML Controller не должен иметь связи с View и Controller не должен в себе иметь переменной View совсем?
То есть Сontroller -> Model -> View получается?
1. Контроллер получает нажатие клавиши, берёт данные с Модели и их изменяет;
2. Модель получает\обновляет данные и отправляет их на Вид?
3. Вид изменять визуал игры;
Потому что из кода на github и текста ниже получается так, нет?
И еще вопрос: Я хочу начать вести мини блог на LinkendIn и написать о MVC, как я его разобрал и понял. Могу ли я ссылаться на это видео? Ссылку на видео я конечно же прикреплю.
Да, получается так. По крайней мере в каноничном представленном MVC схема именно такая. Контроллер не имеет доступа напрямую к View, контроллер изменяет лишь модель.
Опять же уточню, что этой схеме не обязательно следовать, этой схеме много лет и она не совсем адекватно ложится на современный геймдев, но это именно та схема которую представил автор MVC.
Да, пожалуйста, можете на меня ссылаться 🙂 Если какие-то ребята захотят подискутировать и поспорить, пусть пишут мне в комментарии, или в личку в тг, вежливую и нетоксичную конструктивную дискуссию я всегда приветствую.
И ссылку на линкедин тогда тоже попрошу, я там тоже есть бываю хоть и не часто :)
Лайк конечно. Но что-то факт того, что модель дергает вью напрямую без контроллера меня очень удивил. То есть, если мы меняем вью, нам надо ссылку на него поменять и в контроллере и в моделе? Что-то здесь не так...
Абсолютно согласен что тот факт, что модель дёргает вью напрямую без контроллера выглядит очень странно.
Но так указано в научной работе как Трюгве Реенскауга folk.universitetetioslo.no/trygver/2003/javazone-jaoo/MVC_pattern.pdf
(14 страница - две UML диаграммы P11 в правом углу. По ним видно что именно модель шлёт сигнал виду)
так и в той же википедии(хотя конечно вики так себе авторитет) ru.wikipedia.org/wiki/Model-View-Controller (model Updates View)
В защиту могу сказать что это на этапе становления эту странность в MVP и MVVM пофиксили. В MVP появился Passive View который убирал связь модели и вида, в MVVM вообще все перекрутили на датабиндинг
На некоторых статьях по MVC эту проблему так же фиксят как вы рекомендуете, то есть через Controller. Если попробуете загуглить MVC в картинках увидите и тот и другой вариант. Но вариант в видео каноничный, хоть и не значит что строго обязательно следовать ему. Главное чтобы вы решали ваши задачи и вам было удобно
И да, ссылку надо прокидывать на него в двух местах, но только наверху в условном MainScript, что не такая уж и проблема
@@sergeykazantsev1655 Слушай, я посмотрел эти диаграммы и я их понимаю так что в контроллере нет ссылки на вью. Контроллер получает команду от пользователя, меняет модель, а модель уже меняет вью. Контроллер со вью вообще никак не связан.
Блин, точняк. А я в коде получается часть логики считаю в контроллере и передаю на вид(логика победы) а часть логики передаю с модели на вид - результат вращения. В общем тогда пример не самый удачный получился :D Надо будет переписать код примера чтобы контроллер не взаимодействовал с вью
@@PinkPanteRus Исправил :D
@@sergeykazantsev1655 Спасибо!
Все огонь, но ЗИРОКС, а не ксерокс
Вот оно как, и правда