Каждое видео автора смотрю с широко раскрытыми глазами и ушами 😁 В плане объяснения архитектурных приемов автор - просто лучший! Нигде не видел, чтобы кто-то мог объяснять подобные темы настолько просто и наглядно. Я уже не один раз применял знания, полученные с этого канала, в своих проектиках 👍 Моё огромное спасибо автору, не был бы я нищебродом - обязательно бы задонатил.
Очень доходчиво объясняете, спасибо. Про паттерны у вас лучшее объяснение, надеюсь данная тема будет у вас продолжаться, хотелось бы про структурные паттерны. Желаю успехов каналу! p.s. Надеюсь с тапком все ок))
Стейт машина, по моему скромному, должна учится применяться начинающим джунам как можно скорее, потому что меня удивляет, как человек годами может решать задачи путём создания 5 булок, вместо лаконичного и давно известного решения По различиям стратегии и стейта, считаю что стейт подходит для описания поведения одной цельной и неразрывной сущности, а стратегия - для описания изменчивого аспекта какой-то сущности, или семейтсво алгоритмов Писал я как-то раз условный скролер, где использовал стейт машину для описания состояний оружия - стрельба, перезарядка, простой, заклинило и тп. А для реализации логики стрельбы использовал стретегию. Соответственно при подборе какого бонуса, допустим тройного выстрела, я просто менял реализации стрельбы с одной на другую прям на ходу. Вышло довольно занятно Ну и как всегда спасибо за контент!
Спасибо за видео, увидел немного другую реализацию этого патерна (я делал переключение не энамах, а на словаре с типами). Постоянно юзаю этот паттерн в самой основе архитектуры игры (BootstrapState, LocationLoadState, ActiveGameState, PauseState итд). В любом случае спасибо, автор молодец!
@@sergeykazantsev1655 K-syndicate. Чуваки сформулировали архитектуру и создали свой DI. Работяги при переписывании архитектуры на Zenject сталкиваются с циклическими зависимостями. Да и я сам так делал... и на VContainer пытался их машину написать...
Я установил несколько плагинов для более удобной разработки. Ничего волшебного и сверх крутого - просто автоподставка текста, цветовая тема из райдера, хоткеи из Visual Studio. Если интересно - можете написать мне в тг, я скину вам профиль в VS Code, если вы его загрузите у вас будет то же самое)
@@sergeykazantsev1655 Почему вы перешли на VSCode с Райдера (просто всегда видел, как наоборот, на Райдер перехдят). И как VSCode в плане удобства в сравнении с ним?
Скорее LSP. Можнл в качестве альтернативы передавать кнопки по другому, чтобы каждый state вместо обработки методов возвращал список доступных кнопок, но если в них будет уникальная логика, в зависимости от стейта , такое не получится
А почему нельзя то, что реализовано в отдельных классах, запихать в методы и переключать их присваивая делегату определенный метод? Тогда прийдется дописывать еще методы для перехода состояний, получается у состояния есть дополнительно логика для его включения и выключения?
Ну там может быть слишком много логики, чтобы в методы запихивать. В той же игре про шаурму - представьте ход врага и игрока в методы запихивать - повеситься можно)
Классный ролик как всегда. Но есть несколько вопросов =) : 1. Зачем вообще разные методы, если у нас будет расширяться функционал, то мы будем вносить изменения в каждый класс, что нарушает OCP??? Ведь в состояние можно зайти и выйти + постоянное обновление состояния. Следовательно всего 3 метода в базовом классе (Enter, Exit, Tick(float delta)). Если ещё дженериковые стейты сделать, то вообще будет песня, типа State. И добавить класс FSM у которого есть словарь Dictionary , текущее состояние , сетер стейта, методы добавления/ получения текущего и обновление текущего стейта. Если не брать в расчёт первый вопрос и продолжить смотреть текущий вариант, то другой вопрос. 2. Почему все абстрактные методы? ведь это обязывает реализовать метод, а как видели в видео там есть состояния у которых нет реализации, возможно стоит делать виртуальными чтобы не засорять класс-наследник?
1. С моей точки зрения, OCP не запрещает нам вносить изменения в класс. OCP запрещает нам изменять старую логику при модификации, а новая логика в существующем классе - это не изменение а то самое расширение. Если понимать OCP дословно, то тогда на каждый чих нужно будет наследоваться от написанного класса и это будет очень больно и трудно 2. Потому что по хорошему надо так организовать абстракцию чтобы любое состояние как-то выполняло тот или иной метод, и не было пустых. Туда например можно воткнуть Error-ы и информацию о том что починить активную башню невозможно. В конкретном примере да, можно сказать что нарушается LSP и ISP, но виртуальные методы мне кажется всё же мешают ясности и пониманию как то или иное состояние реагирует на тот или иной метод
@@sergeykazantsev1655 1. По текущему примеру. Нужно добавить Поиск врага/ в процессе строительства/починки/ атака врага / оборона - всё это придётся вносить в каждый стейт, а оно нужно ли каждому стейту? А есть уже 20 состояний, придёт ГД и такой давай сделаем чтобы башня при здоровье меньше 10 % усиливала дамаг и издавала спасательные звуки и придётся в 21 классе что-то писать, вместо того чтобы создать 1 класс нового состояния и когда здоровье меньше 10% просто сказать эй башня го в состояние такое-то = ) 2. При абстрактном классе с пустым виртуальным методом ничего не сломается при вызове метода базового класса, следовательно если в наследнике будет или нет конкретная реализация то она корректно отработает в любом случае. Лучше в абстрактном классе оставить пустой виртуальный метод, чем прописывать эесепшены или возвращать null/default в каждом наследнике.
1. Поиск врага не требует, чтобы его по разному реализовали разные состояния, я бы для поиска и стрельбы либо сделал бы флаг CanAttack либо вообще стрелял только если бы state = active То же самое касается усиленного урона, поведение урона башни не зависит от состояния, он зависит от хп, потому той проблемы что вы написали не будет)
2. С вашими аргументами согласен, но как и писал ранее, в идеале абстракция должна быть такой чтобы ни виртуальных методов, ни return null ни эксепшнов не было) но это в идеале
@@sergeykazantsev1655 По назначению, конечно, абсолютно разные) Но, с точки зрения структуры очень даже похожи. За каждое состояние отвечает отдельный класс, также и для каждой команды выделяется собственный класс В классе контекста переключатель состояния выглядит вроде "SetState(new Idle(args))", и аналогично команда выглядит "Send(new InitCommand(args))".
Спасибо за работу. Доставляет. Вопрос более общего плана. Как научиться уметь в архитектуру? Просто есть уровень условного Brackeys, когда главное заставить чтоб оно заработало, и пофиг что там внутри. И есть уровень когда все уже трут за чистую архитектуру, шаблон инжект и прочий космос. Может кто подскажет дорогу, как попасть на второй уровень? Отдельно по запчастям слушаешь, смотришь -все понятно. А откроешь любой проект с гитхаба с примером игрушки построеной по шаблонам, архитектуре и т.д. - и капец. Куда смотреть, как понимать, что за кого отвечает и зачем вообще нужно? Непонятно, одним словом
По архитектуре мое мнение что все упирается в опыт, и чтобы уметь в архитектуру, либо тебе этот опыт кто-то должен передать (лид, ментор) который будет смотреть ваш код, бить по рукам, и объяснять почему так, либо этот опыт надо получить самому. Во втором случае вы пишете игру и в какой то момент понимаете что дальше расширять игру очень сложно и неудобно. В этот момент вы пытаетесь понять почему это произошло, возвращаетесь к теории и понимаете о чем писалось в книжках и про что эти ваши паттерны и SOLID. К счастью или сожалению, архитектуры не стандартизированы, потому тут нет четких шаблонов как в тех же паттернах, все пишут что-то свое но делиться не спешат ибо часто это корпоративная тайна) я так думаю, мне так кажется
Спасибо за ответ А случаем нет волшебного пенделя в виде книги, тутора(eng, ru) с более широким пояснением на конкретной задаче, игре. Почему тут так, а туда лучше пока совсем не надо и т.д. И по типу, чтоб начать - пойдем отсюда, потому что... Я то понимаю, что пендель на самом деле = практика своей головой и руками. Но может есть хоть путеводная тропа))
К сожалению, я не смотрел современные курсы по юнити потому не знаю, как там обстоят дела Есть тг канал по архитектуре в юнити, может обсуждения или прикрепленные ресурсы вам помогут t.me/unity_architecture
Не состояние в словаре, а пул всех созданных состояний. Условно если у нас 5 состояний и если мы между ними переключаемся, лучше их сохранить в коллекции, а не пересоздавать заново каждый раз.
Каждое видео автора смотрю с широко раскрытыми глазами и ушами 😁 В плане объяснения архитектурных приемов автор - просто лучший! Нигде не видел, чтобы кто-то мог объяснять подобные темы настолько просто и наглядно. Я уже не один раз применял знания, полученные с этого канала, в своих проектиках 👍 Моё огромное спасибо автору, не был бы я нищебродом - обязательно бы задонатил.
Очень доходчиво объясняете, спасибо.
Про паттерны у вас лучшее объяснение, надеюсь данная тема будет у вас продолжаться, хотелось бы про структурные паттерны.
Желаю успехов каналу!
p.s. Надеюсь с тапком все ок))
Спасибо за тёплые слова) Тапок в порядке :D
Стейт машина, по моему скромному, должна учится применяться начинающим джунам как можно скорее, потому что меня удивляет, как человек годами может решать задачи путём создания 5 булок, вместо лаконичного и давно известного решения
По различиям стратегии и стейта, считаю что стейт подходит для описания поведения одной цельной и неразрывной сущности, а стратегия - для описания изменчивого аспекта какой-то сущности, или семейтсво алгоритмов
Писал я как-то раз условный скролер, где использовал стейт машину для описания состояний оружия - стрельба, перезарядка, простой, заклинило и тп.
А для реализации логики стрельбы использовал стретегию. Соответственно при подборе какого бонуса, допустим тройного выстрела, я просто менял реализации стрельбы с одной на другую прям на ходу. Вышло довольно занятно
Ну и как всегда спасибо за контент!
и шо много заработал?
Спасибо за видео, увидел немного другую реализацию этого патерна (я делал переключение не энамах, а на словаре с типами). Постоянно юзаю этот паттерн в самой основе архитектуры игры (BootstrapState, LocationLoadState, ActiveGameState, PauseState итд). В любом случае спасибо, автор молодец!
Молодец!! Самое лучшее объяснение паттерна state на ютубе
+REP за сравнения State и Strategy. На собесах спрашиваюь (мидл). От себя добавлю: не использовать синдикатовскую машину - циклическая зависимость.
А что такое синдикатовская машина? Оо
@@sergeykazantsev1655 K-syndicate. Чуваки сформулировали архитектуру и создали свой DI. Работяги при переписывании архитектуры на Zenject сталкиваются с циклическими зависимостями. Да и я сам так делал... и на VContainer пытался их машину написать...
@@sergeykazantsev1655 Думаю он про K-Syndicate
Понятно, надо будет посмотреть чего они там наворотили)
Спасибо большое за лаконичное объяснение паттерна, очень полезно! На смузи закинул)
Душевно благодарю) получил)
Спасибо, за твои уроки, очень понятно и интересно.
Спасибо! Коммент для продвижения)
Не посмотрел, но видос крутой
а как ты это понял? :D
А какую тему в VS Code используете? И может дадите какие-то советы/рекомендации по настройке VS Code для Unity?
Я установил несколько плагинов для более удобной разработки. Ничего волшебного и сверх крутого - просто автоподставка текста, цветовая тема из райдера, хоткеи из Visual Studio.
Если интересно - можете написать мне в тг, я скину вам профиль в VS Code, если вы его загрузите у вас будет то же самое)
@@sergeykazantsev1655 Почему вы перешли на VSCode с Райдера (просто всегда видел, как наоборот, на Райдер перехдят). И как VSCode в плане удобства в сравнении с ним?
Райдер лучше, но VS Code бесплатный :D
Автора рекомендую, приятно посмотреть.
TowerState больше ISP или LSP нарушает? Раздутая абстракция, не реализуемые в наследниках методы интерфейса
Скорее LSP. Можнл в качестве альтернативы передавать кнопки по другому, чтобы каждый state вместо обработки методов возвращал список доступных кнопок, но если в них будет уникальная логика, в зависимости от стейта , такое не получится
А почему нельзя то, что реализовано в отдельных классах, запихать в методы и переключать их присваивая делегату определенный метод? Тогда прийдется дописывать еще методы для перехода состояний, получается у состояния есть дополнительно логика для его включения и выключения?
Ну там может быть слишком много логики, чтобы в методы запихивать. В той же игре про шаурму - представьте ход врага и игрока в методы запихивать - повеситься можно)
Несколько раз пересмотрел и понял что я про стратегию подумал.
бывает)
Классный ролик как всегда.
Но есть несколько вопросов =) :
1. Зачем вообще разные методы, если у нас будет расширяться функционал, то мы будем вносить изменения в каждый класс, что нарушает OCP??? Ведь в состояние можно зайти и выйти + постоянное обновление состояния. Следовательно всего 3 метода в базовом классе (Enter, Exit, Tick(float delta)). Если ещё дженериковые стейты сделать, то вообще будет песня, типа State. И добавить класс FSM у которого есть словарь Dictionary , текущее состояние , сетер стейта, методы добавления/ получения текущего и обновление текущего стейта.
Если не брать в расчёт первый вопрос и продолжить смотреть текущий вариант, то другой вопрос.
2. Почему все абстрактные методы? ведь это обязывает реализовать метод, а как видели в видео там есть состояния у которых нет реализации, возможно стоит делать виртуальными чтобы не засорять класс-наследник?
1. С моей точки зрения, OCP не запрещает нам вносить изменения в класс. OCP запрещает нам изменять старую логику при модификации, а новая логика в существующем классе - это не изменение а то самое расширение. Если понимать OCP дословно, то тогда на каждый чих нужно будет наследоваться от написанного класса и это будет очень больно и трудно
2. Потому что по хорошему надо так организовать абстракцию чтобы любое состояние как-то выполняло тот или иной метод, и не было пустых. Туда например можно воткнуть Error-ы и информацию о том что починить активную башню невозможно. В конкретном примере да, можно сказать что нарушается LSP и ISP, но виртуальные методы мне кажется всё же мешают ясности и пониманию как то или иное состояние реагирует на тот или иной метод
@@sergeykazantsev1655 1. По текущему примеру.
Нужно добавить Поиск врага/ в процессе строительства/починки/ атака врага / оборона - всё это придётся вносить в каждый стейт, а оно нужно ли каждому стейту?
А есть уже 20 состояний, придёт ГД и такой давай сделаем чтобы башня при здоровье меньше 10 % усиливала дамаг и издавала спасательные звуки и придётся в 21 классе что-то писать, вместо того чтобы создать 1 класс нового состояния и когда здоровье меньше 10% просто сказать эй башня го в состояние такое-то = )
2. При абстрактном классе с пустым виртуальным методом ничего не сломается при вызове метода базового класса, следовательно если в наследнике будет или нет конкретная реализация то она корректно отработает в любом случае. Лучше в абстрактном классе оставить пустой виртуальный метод, чем прописывать эесепшены или возвращать null/default в каждом наследнике.
1. Поиск врага не требует, чтобы его по разному реализовали разные состояния, я бы для поиска и стрельбы либо сделал бы флаг CanAttack либо вообще стрелял только если бы state = active
То же самое касается усиленного урона, поведение урона башни не зависит от состояния, он зависит от хп, потому той проблемы что вы написали не будет)
2. С вашими аргументами согласен, но как и писал ранее, в идеале абстракция должна быть такой чтобы ни виртуальных методов, ни return null ни эксепшнов не было) но это в идеале
@@sergeykazantsev1655 это геймдев, идеальных проектировок не будет =) постоянно что-то меняется
Паттерн Состояние больше похож на паттерн Команда, чем на Стратегию, имхо)
А в чём, по вашему, схожесть команды и состояния?)
@@sergeykazantsev1655 По назначению, конечно, абсолютно разные) Но, с точки зрения структуры очень даже похожи.
За каждое состояние отвечает отдельный класс, также и для каждой команды выделяется собственный класс
В классе контекста переключатель состояния выглядит вроде "SetState(new Idle(args))", и аналогично команда выглядит "Send(new InitCommand(args))".
ну в этом да, полиморфизм во всей его красоте)
Новое видео)
Cool)
Спасибо за работу. Доставляет.
Вопрос более общего плана. Как научиться уметь в архитектуру?
Просто есть уровень условного Brackeys, когда главное заставить чтоб оно заработало, и пофиг что там внутри.
И есть уровень когда все уже трут за чистую архитектуру, шаблон инжект и прочий космос.
Может кто подскажет дорогу, как попасть на второй уровень? Отдельно по запчастям слушаешь, смотришь -все понятно. А откроешь любой проект с гитхаба с примером игрушки построеной по шаблонам, архитектуре и т.д. - и капец. Куда смотреть, как понимать, что за кого отвечает и зачем вообще нужно?
Непонятно, одним словом
По архитектуре мое мнение что все упирается в опыт, и чтобы уметь в архитектуру, либо тебе этот опыт кто-то должен передать (лид, ментор) который будет смотреть ваш код, бить по рукам, и объяснять почему так, либо этот опыт надо получить самому.
Во втором случае вы пишете игру и в какой то момент понимаете что дальше расширять игру очень сложно и неудобно. В этот момент вы пытаетесь понять почему это произошло, возвращаетесь к теории и понимаете о чем писалось в книжках и про что эти ваши паттерны и SOLID.
К счастью или сожалению, архитектуры не стандартизированы, потому тут нет четких шаблонов как в тех же паттернах, все пишут что-то свое но делиться не спешат ибо часто это корпоративная тайна) я так думаю, мне так кажется
Спасибо за ответ
А случаем нет волшебного пенделя в виде книги, тутора(eng, ru) с более широким пояснением на конкретной задаче, игре. Почему тут так, а туда лучше пока совсем не надо и т.д.
И по типу, чтоб начать - пойдем отсюда, потому что...
Я то понимаю, что пендель на самом деле = практика своей головой и руками.
Но может есть хоть путеводная тропа))
К сожалению, я не смотрел современные курсы по юнити потому не знаю, как там обстоят дела
Есть тг канал по архитектуре в юнити, может обсуждения или прикрепленные ресурсы вам помогут t.me/unity_architecture
Зачем хранить состояние в словаре? Почему не использовать статический класс? Синглтон это слишком)
Не состояние в словаре, а пул всех созданных состояний. Условно если у нас 5 состояний и если мы между ними переключаемся, лучше их сохранить в коллекции, а не пересоздавать заново каждый раз.
@@sergeykazantsev1655 А статика не пойдет - потому что экземпляров обьектов может быть много, и тогда все состояния будую для всез одинаковы, понял.