Паттерн состояние в unity 3D
Вставка
- Опубліковано 9 чер 2024
- Продолжаем разбираться в паттернах проектирования в рамках unity3D и C#. Сегодня в выпуске паттерн состояние с различными вариантами переходов
Ссылка на Discord - / discord
Паттерн стратегия - • Паттерны стратегия в u...
Паттерн наблюдатель - • Паттерн наблюдатель в ...
Паттерн декоратор - • Паттерн декоратор в un...
Принципы солид - • ООП вопросы на юнити с...
Паблик игроделов - special3d
"00:00 - Введение"
"00:30 - Описание проблемы"
"03:13 - Реализация паттерна"
"05:35 - Определение паттерна"
"07:20 - Глобальные состояния"
"08:51 - Варианты смены состояний"
"10:45 - Заключение"
Поддержка канала:
Patreon - www.patreon.com/user?u=32502669
В крипте:
BTC - 16WmTb4VTFGYrwEjjnMKNNMMzsMB1rPEqD
ETH - 0x8d35406f8317b846528d0a9ea4a34ce59968dff2
XRP - rLW9gnQo7BQhU6igk5keqYnH3TVrCxGRzm (TAG - 1438215071)
LTC- MNSWdzdVsUMnozSU5HhUPEscfxaUK3Fdck
#unity3d #statemachine #patterns #gamedev #ityoutubersru
Как всегда прекрасно, Максим Паттернов))
Вроде как круто, но в тоже время довольно тяжко воспринимать. Я этот паттерн вдоль и поперёк знаю, но местами было трудно следить за видео. Есть ощущения что видос больше для тех, кто уже знаком с этим паттерном.
Это кста не упрёк, просто чтобы автор лучше понимал, для какой аудитории делает видева.
Спасибо за полезный контент.
Все верно, цель канала - подхватывать тех, кто уже стал на эту дорогу
@@gaitavr1992 , может в качестве улучшения юзер френдли вашего канала зальете на гитхаб и ссылку в описание?
@@gamedev_level_up по паттернам нечего заливать, это выдуманный код
@@gaitavr1992 макс, посоветуй пожалуйста Musthave статьи или книги по паттернам, да и вообще по unity
@@gaitavr1992 Ну все понимают, что выдуманный, но всё же, было бы проще и привычнее полазить по файликам на гите, чем перематывать по 100 раз видео)
p.s. Такого информативного контента на ютубе почти нет, а тут ещё и на русском) Спасибо
Как всегда, все на высшем уровне! Устроился в геймдев и теперь стабильно использую твои ролики для работы) Продолжай том же духе! Спасибо большое за твой труд, такого качественного контента на рускоязычном сегменте крайне мало!
Какие ролики помогают?
@@gaitavr1992 рефакторинг
@@gaitavr1992 По началу базовые были самые просматриваемые такие как: атрибуты, расширения, делегаты и т.п. Сейчас уже паттерны, так как грамотно подобрать архитектуру при разработке это чертовски важно. Правда из-за разницы в уровнях, приходится ролик продолжительностью минут в 10 пересматривать раз за разом, но я думаю это уже временные издержки)
Главное столкнуться на практике с проблемой, чтобы понимать решение с помощью паттерна
@@gaitavr1992 Получается все топорно, но верно. При рефакторинге уже идет понимание))
Очень рад, что наткнулся на этот канал!
Очень интересно и понятно объясняете, спасибо!!!
Максим, когда осенью готовился к своим занятиям -нигде не нашел норм видосов по шаблонам именно в Юнити. Шикарные уроки!! Людям это нужно
Отличный видос! Очень нужный паттерн
Очень доходчиво и понятно!
Спасибо, было очень полезно!
Шикарно, благодарю Максим)
Всё очень прекрасно. По поводу создания дополнительных класса Transition - тут же контролируется и в какие State может перейти объект. И логика будет в них. Выглядит очень удобно.
Как раз делал систему передвижения для игрока через if/else, если стоим на земле или плывём по воде и т.п. После ролика понял, что это все можно вынести в состояние и получить более удобную и гибкую систему.
Конечно, чтобы вынести все зависимости из контекста, пришлось поломать голову, но оно того стоит. Спасибо за добротный контент)
Надеюсь перенос пройдёт гладко) не всегда так получается
Спасибо, за ролик! Всё рассказано понятно, размеренно. Буду применять. А то хоть я и разбил код на вьюшки, модели и контроллеры, а мешанины все равно много получается.
Отличное, полезное, познавательное видео
Большое спасибо, а то я оказывается использовал стратегию для смены состояний
Пожелание: разбить ролик на части (сделать закладки), вступление, основная часть и заключение, плюс в основную часть добавить закладки на примеры кода и основные моменты. Многим сдесь будет удобно искать примеры кода в будущем. Второе: фон за теукстом размывать и сделать максимально контрасным фон и текст и НЕ использовать эффекты текстов и т.д. Посоветовал бы сделать один раз шаблон и им пользоваться. А так все отлично. Спасибо за ролик.
лайк и коммент, автору респект,)
Спасибо. А как смену анимации вплести в данную реализацию паттерна? Пытаюсь реализовать состояние NPC, все вроде понятно и работает, но не пойму, как подключать разные анимации (атака, погоня, патрулирование) при таком подходе. Примеры переключения анимаций в ютубе все с наследованием от StateMachineBehavior, но как-то интуитивно не хочется его использовать.
огонь, всё супер чётко, спасибо
(☞゚ヮ゚)☞
То что нужно.
Добрый день, Максим. Мне Очень нравятся ваши ролики и подход преподавания. Есть ли у вас курсы по паттернам? Если нет, то могу посоветовать какого рода курсы бы приглянулись изучающим данную тему. Пример "Проект в юнити с использованием паттерна проектирования". Можно на udemy залить или как вам угодно.
Для зрителя - Ставь лайк комменту, если хочешь такой курс.
спасибо!
Спасибо.
Ещё бы хотелось увидеть видос на тему специфики юнити при программировании. Как конфликтует система компонентов юнити и ООП. Как это влияет на архитектуру юнити приложения. Как решать проблемы с пробрасыванием зависимостей. Нужны ли архитектурные паттерны в юнити (mvp, mvc и т.д). Ну и ECS как архитектурное решение в ту же кучу.
Zenject для зависимостей
Присоединяюсь к вопросу по MVP. Впечатление такое, что всем оно нужно, но никто не может объяснить, зачем.
А что делать если метод остался пустым? К примеру если у меня не было бы поля Text то можно ли было оставить методы в некоторых состояниях пустыми? Спасибо.
Класс Transition еще глобальным для всех стейтов может быть, к примеру для разновидностей ботов
Если они не сложные
Спасибо
Есть очень хорошая и гибкая реализация этого паттерна на ScriptableObject. Шикарно работает.
Спасибо
Дякую
Контент огонь. Наверное по паттернам в Unity ничего подобного на рус. ютубе нет
Какая разница в юнити этот патерн или не в юнити
Супер, больше бы таких каналов не за что не забивай на ютуб! Можешь сделать пожалуйста видео, если будет время, как стоит подходить к реализации паттерна состояние или его аналога в случае работы с фреймворком на ECS будь то unity dots или LeoEcs
С ecs проблема, оно сырое, как недоваренные пельмени. Я бы подождал чего-то более стабильногл
В ECS состояние это набор компонентов и их значений
@@gaitavr1992 Entitas давно уже допилен, а LeoECS постоянно допиливается и уже используется в продакшене.
То, что я видел - далеко от допиленного
@@gaitavr1992 О буду рад, аргументированной критике. Спасибо заранее.
а state и state machine это одно и тоже или это разные вещи? А ещё можно попросить вас выкладывать код, хотелось бы пощупать его что бы лучше понять.
Одно и тоже. По паттернам нет смысла код выкладывать, так как он выдуманный
@@gaitavr1992, подскажите пожалуйста, в репозитории по товердефенс есть коммиты по урокам? Или только текущий проект? Сейчас повторяю пошагово Ваш проект и иногда по невнимательности что-то пропускаю, а потом не могу понять, где накосячил. Также подвопрос. Исходный проект с игрой это переработка статьи с Catlike Coding?
Недавно начал делать ветки под каждый урок и вливать их одним коммитом для удобства. По поводу cat like coding, да, я взял основу и пошел дальше
Превьюха сочная)
Ух , никогда не учил паттерны, но и процедурным кодом , тоже уже не пишу.Оказывается всё уже придумали и додумали за меня и нужно просто найти паттерн для то или иной ситуации... Немного разочаровывающие умозаключение . Столько времени было потрачено на придумывание систем , если бы я сразу учил эти поведения ....Спасибо большое за урок жду новых паттернов ! )
Очень часто паттерн не помогает и приходится его нарушать
@@gaitavr1992 Но знания о паттернах экономят немало времени , даже если приходиться нарушать их конструкцию, это всё равно быстрее, чем придумывать логику с чистого листа.
Согласен
хорош
Отлично рассказано, но не до конца понятен дефолтный вариант перехода состояний. Условно говоря я должен в каждом стейте в GoToNextState забить все условия на основе которых он перескочит в то или иное состояние? До кучи к этому надо будет создать следующий стейт и как-то его вернуть в контекст?
Речь идет о втором варианте, где контекст сам решает когда переключать?
@@gaitavr1992 вроде как да. Но я и тему со switch state не очень понял. Типа туда передается дженерик, это вроде понятно. Но где происходит сам контроль и решение по переключению.
Так где дженерик был, состояния сами выбирают следующее. В второй вариант, когда состояния идут друг за другом и контекст по очереди их выполняет
@@gaitavr1992 А, во втором варианте в старте очередь задается, и они просто подряд выполняются. Примерно дошло, надо на практике попробовать.
Здравствуйте, Максим. Отличное видео, спасибо. Не знаете ли Вы реальных проектов с хорошим открытым исходным кодом и, в частности, с реализацией паттерна состояние? Проекты любой тематики, не обязательно игры и юнити. Хотелось бы увидеть на практике использование данного паттерна, так как остались некоторые вопросы по реализации. Например, как вызывать общие функции в классе-контексте из классов-состояний не нарушая инкапсуляцию, оставляя внутренние методы приватными для внешнего кода, но открытыми для классов-состояний.
Мне недавно на ревью стейт машину скинули, сделаю обзор. А по поводу контекста - выносить в интерфейс явно и работать с ним внутри состояний
@@gaitavr1992 Спасибо, буду ждать ревью. Вы очень доходчиво и понятно объясняете, хотелось бы увидеть видео о паттерне посетитель, visitor. Сколько о нем не читал, так до конца и не понял, когда его нужно использовать.
Он один из самых сложных
Вместо листа со стейтами используй дикшинари Dictionary() и в
SwitchState() where T : BaseState {
if(!_allStates.TryGetValue(typeof(T), out _currentState) {
//обработать ошибку если стейт не найден.
}
}
Что за класс SliderFiller, не нахожу. Да и компонента такого.
Привет! При использовании паттерна возникают неудобства, когда состояние нуждается в редактировании закрытых (приватных) членов контекста. Примером может служить состояние персонажа:
В состоянии "Жив" персонаж может получать урон и как следствие поле его текущего здоровья меняется. Однако это поле не должно быть доступно изменению из вне никому, кроме класса состояния "Жив". Есть ли совет по решению этих проблем? Я нахожу 2 решения, где первое заключается в открытии полей для редактирования из вне (что является жутким костылем), а второе в использовании unsafe кода и указателей.
Либо выделять модель состояния и модифицировать ее либо через интерфейс работать с контекстом. Никакие указателей)
@@gaitavr1992 Хорошо, посмотрим что можно сделать:) Мог бы ты как-нибудь рассказать об unsafe коде и указателях? Как движок реагирует на изменение значений в памяти и т.п. По-моему очень интересная тема и много подводных камней.
Было бы интересно услышать мнение эксперта.
Я как нибудь попробую, но эта тема для меня не очень изведанная. Многое уже забылось, а многое и не встречал
@@gaitavr1992 Спасибо за это видео, первое настолько полное и грамотное объяснение FSM, которое я встречал. Хочу узнать твое мнение:
Тоже оочень долго думал над лучшей реализацией этого паттерна и вот к чему сейчас пришел:
1. Класс контекст НЕ должен реализовывать интерфейсы, как IStateSwitcher, это нарушает инкапсуляцию, тк любой вызывающий код может привести его и изменить состояние. Вместо этого делаем класс StateSwitcher, который хранит в себе логику смены состояний и само состояние. Класс StateSwitcher находится внутри класса-контекст.
Вот примерный интерфейс класса StateSwitcher:
void SwitchState() {//logic...} where ConcreteStateT : AbstractStateT
AbstractStateT CurrentState => _currentState;
2. Классы-состояния следует делать приватными и внутренними к классу-контексту, а в их конструктор стоит передавать класс-контекст. Пример класса-состояния:
pastebin.com/J5wbGrh1
Из плюсов: больше инкапсуляции = больше безопасности использования.
Из минусов: Классы-состояния больше нигде нельзя использовать, кроме как в классе контексте, в котором они содержатся.
В реальном проекте этого сложно добиться, когда все разрастается.
считаю этот паттерн обязательным для изучения/использования, у меня просто 2 примера игр над которыми я работал в одном и том же жанре с разницей почти 5 лет, в котором можно улучшать разные постройки, хоть и в большинстве случаев улучшение постройки не меняло ее механик, но были такие что совмещали в себе разные механики, это был ад с кучей наследований чтоб сделать нужные механики для одного юнита тратилось до нескольких дней работы, щас сделав все на стейтах, такой юнит может сделать даже геймдизайнер, просто добавив или убрав пару строчек в json файл
Или через scriptable objects, как insane one показывал
ECS
хорошие видео ,хотя и не много трудно уловить смысл , если ты не синьер, из за огромного количества профессиональных терминов, очень полезно и интерсно
Этот паттерн должен знать даже джуниор-мидл
Твои видео как самородки в русскоязычной части ютуба
не только в русскоязычной
Если нужны состояния, которые переиспользуются с разными контекстами, то единственный вариант их изменений это вынос переходов в отдельный класс? Я правильно понимаю?
А можно подробней пример, где разные контексты используют одинаковые состояния?
@@gaitavr1992 Ну, положим у нас есть несколько юнитов. Солдат (IdleState и WalkingState), Дракон (IdleState, WalkingState и FlyingState) и например Жаба, (IdleState, WalkingState и SwimmingState). Контекстами в данном примере служат конкретные реализации юнита (солдат, дракон и жаба). Очень не хотелось бы писать каждому из юнитов свой IdleState и WalkingState, это, согласитесь, просто отвратительно. Они ведь одинаковые. По сути юниты отличаются лишь набором стейтов и переходами между ними. Как стоит быть в такой ситуации? Я довольно долго с этой логической проблемой в голове сражался, но так ни к чему умнее выноса переходов состояний в отдельный класс не придумал. Буду рад совету :) А, кстати, если будете отвечать, то отвечайте без оглядки на мои навыки программирования, я более чем уверен, что смогу уловить мысль любого уровня.
Выглядит так, будто переходами может управлять сам контекст в зависимости от ввода или еще какихто событий
@@gaitavr1992 Благодарю за ответ
Либо я как-то просмотрел, либо это надо учесть: не хватает примеров клиентского кода по работе с стейт машиной, чтобы логическая завершенность что ли была, и понятно было до конца, куда мы приехали
А можно разбор нового input system?
Я еще не пользовался
У меня возник вопрос как передавать вечно изменяющиеся параметры, например трансформ врага если кидать его в конструктор будет ошибка, а если в апдейт будет ли это рационального? Если заметили и ничего не поняли отпишитесь я лучше опишу вопрос
Враг должен сам работать со своим трансформом
@@gaitavr1992 а как тогда реализовать состояние патрулирования? Если только враг может работать с трансформом?
Врагу задаются точки и он ходит. Если вопрос про сам класс состояния, то можно вынести метод move у врага и состояние будет использовать его
@@gaitavr1992 то есть нужно будет просто вынести движение, а не сам класс с состоянием патрулирования?
Состояние патрулирования будет управлять логикой перемещения, а функционал предоставится внутри врага
А что делать с методом SwitchState? Он ведь публичный получается
Явно интерфейс указать, тогда остальной код не будет о нем знать
@@gaitavr1992 спасибо. Буду применять
Запускать стейт машину как корутину - норм практика ведь?
Можете пояснить, что подразумевается под контекстом?
Класс из которого выносится логика в состояния, для остального кода с ним точно также можно работать
@@gaitavr1992 то-есть контекст - это класс из которого мы вынесли логику в состояния?
Да
@@gaitavr1992 Значит я правильно все понял, спасибо большое. Ролики класс
Получается что Animator и есть пример машины состояний. Если я правильно понял. Дякую. Мирного неба.
Код на гитхаб плиз
7:13 1 -> 3 ?
Да как так-то?
Ты же сам на 6:30 говорил, что знание о конкретных состояниях это грубейшая ошибка
Так это пример ошибки, нарушающей паттерн
Там гоаорится не про знание клиента о состоянии, а о том что состояния могут знать друг о друге
Ну и да, я бы все равно не говорил, что это то как всегда нужно делать стейтмашину. Вот допустим банальный парсер какого-нибудь сетевого протокола, который поверх TCP/IP. Допустим Http. Тут не будет добавляться новых состояний с одной стороны, с другой - логика будет в одном месте, а не размазана по куче классов.
Да, я понимаю, что в случаях когда мы переходим на уровень выше - лучше использовать что-то типа того что в видео, но прозвучала мысль, про то что нам нужно всегда так делать, я вот с этим не совсем согласен. Да и майки, судя по тому как у них парсер того же Http реализован - тоже.
В остальном - хорошее видео. Я бы советовал его тем, кто только знакомится с паттернами.
Не совсем понял при чем парсер к стейт машине? Если несколько степов то это цепочка обязанностей
@@gaitavr1992
Кхм. Я могу быть не прав, нам лексический анализ на втором курсе давали, но классический парсер - это стейтмашина, которая получает на вход последовательность лексем, затем - обрабатывает их и в зависимости от правил грамматики - позволяет построить структуру, либо завершиться ошибкой.
Банально: Text - мы получили вот такую вот строку, лексер разбил это на: [начало открывающего тега, текст, конец тега, текст, начало закрывающего тега, текст, конец тега], парсер, который должен построить DOM-дерево - должен иметь состояния, чтобы в зависимости от него - понимать - должны ли мы создать ноду, должны ли мы в метаданные документа что-то добавить или вообще кинуть ошибку. Как без состояний этот парсер-то должен работать?
Теперь понял, так а где противоречие в видео?
@@gaitavr1992 Я вроде не говорил о противоречиях, просто отметил, что не для каждой стейтмашины нужно пользоваться паттерном состояние (банально стейтмашину в 100 строк, лично я бы не стал резать на несколько классов, особенно, если она - является чем-то классическим и не предполагает изменений).
Ну да ладно. Я же вроде сказал, что видео - хорошее и новичкам полезно будет.
А вот может кто-то ответит на такой, возможно нубский, вопрос? Все, что я о паттернах нахожу, даже на примере юнити, все красиво и понятно, но не пивязано к монобихевиорам. к чему я это. когда описывают какую-то вещь вроде наследования сущностей от какой-то общей болванки( человек: солдат, медик, гражданский) и красиво юзают всевозможные полиморфные штуки, то как эти иерархии привязываются к геймобжектам, олицетворяющим те сущности? У Сакутина видел визитер, где результат рейкастхита обрабатывался логикой визитера, но иерархия хитов полностью отвязана от игры. тут то я и сдулся. +-есть понимание применения тех или иных штук, но в разрезе юнити туплю. хелп)
Монобехи точно также могут учавствовать в этом параде паттернов, если нужно. Это тоже классы
Ох, как сложно, но как хочется понять это всё. Напрягаемсяяяя ыыыыыыыыыыыыыыыыыыыыыыыы
За такую диаграмму классов меня бы выебали, если честно. Лучше держись стандарта uml. Хорошо сделанная диаграмма более информативна чем окна с кодом, которые в экран не влазят.
Не, ну серьёзно, ты оооооочень сложно всё объясняешь. Поймут лишь те, кто и так на твоём же уровне это всё знает.
Хорошее объяснение для тех, кто об этом слышал, но не очень понимал, где и как применить.
Спасибо, Макс!
Попробую заглянуть еще позже и всё таки понять, о чём ты говоришь:D
Серьезно, это сложно?) максимально подробно и прозрачно)
Попробуй со звуком посмотреть
@@vatyunga аа, так вот в чём дело!
а при чем тут Unity в названии роликов ? каждый раз смотрю , надеясь что покажут наконец понятно для новичков. а тут движком и не пахнет. я вот опять нихрена с такой подачей не понял! хотя как раз для новичков это сложная для понимания вещь. показал бы куда какие скрипты накидываешь и как процесс самой организации паттерна происходит.
А что тут сложного, берешь и применяешь. А если новичок, то иди учиться.
Не сочти за грубость, но ты не от Романа Сакутина? Он недавно подкинул каналу подписчиков, однако мне всегда казалось, что его канал больше про хейт и хайп, чем про разработку. Если же по существу, то открой список видео на канале. Особенно пошаговый разбор создания товердефенс. Там как раз рассказывается, что и куда нужно "накидывать". А канал у Максима архиполезный.
Немного оффтопа. Хочешь контент совсем для новичков - сходи на какой-нибудь Игрострой, посмотри на подачу и код местного автора-неадеквата. Там всё очень понятно для новичков, но проблема в том, что взрослый мужик пишет код как школьник, а любые комменты с критикой кода трет. При чем критика не вида "твой код говно", а вполне себе листинги с кодом.
@@andrey_aka_skif я не сказал, что канал плохой(иначе не был бы подписчиком), я лишь прошу более расширенной подачи материала. Паттерны просто в сишарп и в движке немного разные вещи. Начальные знания по языку есть. Вот и прошу автора чуть шире все показывать. Игростой уже давно в прошлом. Как раз и смотрю более продвинутые каналы уже.и не забывай о том, что то, что уже понятно тебе, не совсем понятно другим. Как раз архитектура слабое место у меня
@@tomasgammister5776 , реально, повтори товердефенс. Я как раз в процессе. Это архи крутой материал. Придётся, конечно, параллельно ликвидировать пробелы в знаниях, но это как раз материал степ бай степ.
@@tomasgammister5776 кстати, не на столько они и разные. Некоторые наоборот считают, что упор на монобихевиер это зло и самое слабое место юнити. Делают разного рода контроллеры, которые задействуют один-два монобеха в сцене, реализуя подобие ecs. Это конечно жуткий велосипед, но его использование имеет некоторые архитектурные причины. Как пример можно привести событийную модель (хоть это немного и про другое). Можно юзать юнитиэвенты, а можно и шарповые делегаты. Короче, не надо привязываться к монобеху как к единственному способу накинуть объекту логики. В том же товердефенсе фабрика реализована через скриптаблобжект, что позволяет сериализировать ссылки на объекты вне сцены (и наоборот, не даёт сохранить ссылки на объекты сцены).