Паттерн FSM или Машина Конечных Состояний. Как использовать в Unity?
Вставка
- Опубліковано 30 лип 2024
- Поддержать канал:
www.donationalerts.com/r/game...
paypal.me/gamedevlavka
Очередной паттерн для разработки игр на движке Unity! Finite State Machine, или кратко FSM, или на русском - машина конечных состояний. Он используется для определения графа состояний для NPC, для состояний игры, для поведения UI, и для многих других вещей, набор состояний которых предопределен и понятен. Очень важный паттерн для тех, кто уже шарит в разработке и хотел бы немножко углубить свои знания и понимание работы некоторых алгоритмов. Старался рассказать понятно, но если не понятно - напиши об этом в комментариях, будем с этим что-то делать. И да, подписываемся на канал, лайки ставим! Enjoy!
======================================
Купить билеты на WN Conference:
wnconf.com/
Промокод на скидон: gamedevlavka
Зарегистрироваться на шоукейс на WN Conference:
wnconf.com/#for-developers
======================================
___
Лавка Разработчика в других соц. сетях, добавляйтесь!
t.me/gamedevlavka - телеграм канал Лавки Разработчика
t.me/gamedevtavern - ламповый чат
/ discord - дискорд
gamedevlavka - вконтактик
__________
0:00 О конференции WN Conference
2:28 Вступление
3:56 Пишем FSM
9:36 Пишем состояния для примера
14:35 Пишем пример употребления
16:22 Сетапим сцену и смотрим как работает пример FSM
Урок хороший, но как мне кажется совсем для новичков, а для новичков куча реализаций. Хотелось бы наверное более углубиться в раскрытие темы, т.к. на базе State machine строят архитектуры приложений. Поговорить о вариациях Transitions, возможно зацепить реализации с async, может быть построить какой-нибудь WindowManager. Построение простой архитектуры через StateMachine. Связывание например StateMachine и View. Может быть StateMachine и Zenject рассмотреть. Просто паттерн очень часто используется, а качественных уроков по его применению не особо много, кроме условного состояния персонажа. А так спасибо за видос!
Не, Zenject не надо, эту какаху вообще не надо
@@samserious5483 а какая лучшая альтернатива?
@@almightiey0.0 написать то, что лучше всего подходит проекту конуретному
@@samserious5483 zenject используют повсеместно. и неспроста - это лучший di контейнер. единственный минус заключается в его массивности и, наверное, в сложности освоения. для масштабных проектов - идеальный фреймворк. однако, для небольших лучше взять просто сервис локатор и не парится
Отличный урок. Хотелось бы еще одним щелчком скачать данный пример.
Спасибо за урок!
Наверное лучший канал по юньке который я видел...
Спасибо за полезный контент.
неплохо вышло, но не могу не заметить пару замечаний
1) метод AddState лучше сделать генерик, как и SetState, тогда не придется вызывать метод GetType, который выполняется в рантайме, а заменить на typeof(T), выполняющийся на этапе компиляции
2) можно кэшировать Type (который также будет браться через typeof) последнего установленного стейта и в проверке на одинаковый тип тоже можно убрать GetType, а оставить что то типа:
if (currentStateType == typeof(T)) return
жду новых видосов)
вообще у меня на гите лежит еще более сложная стейт машина, мог бы дать тебе на ревью)
Со всем согласен) мне главное смысл показать)
А реализаций, как я и сказал, чуть ли не бесконечность)
На гите давай, с радостью гляну)
@@gamedevlavka скину в телегу, здесь удаляет
Круто спасибо!
Отличное видео. Кто хочет понять Стэйт Машину- Вам сюда. Автор всё отлично объяснил.
Хорошее видео. Не посмотрел раньше из-за сессии + сейчас в проекте я бомбанул и переписываю машину состоянии))0)
Ещё приятно слышать твой радостный голос в видео))
Радостный? А обычно какой?)
@@gamedevlavka Я помню как серьёзный и вдумчивый. Значит из-за универа забыл :Р
Даа) Область применения фсм у меня страдает) жаль что без транзишн с ней у меня как раз проблемы)
Ещё бы урок по zenject
Ничего не понял, но очень интересно.
А ничего и не надо понимать. Напридумывали всякой ерунды (паттернов), мало было GOF - так вот получите 100+ паттернов. И реализуют эту выдумку разными способами. И паттерны и гибкая методология и фреймворки - легаси код на выходе ) А есть ещё и антипаттерны...
Паттерн должен был решать типовую задачу, но когда их стало более ста, когда у каждого стало несколько реализаций, когда базовый mvc трактуют как тонкий-толстый контроллер и устраивают холивары (и еще какие и на любых уровнях от джуна до синьора)...есть над чем подумать.
А в чем твой пункт? Паттерны не нужны? Или их не нужно изучать? Поясни мысль.
@@user-sx7vo6kg8t паттерны не работают и не решают задачи бизнеса. Да, по сути они не нужны в силу невозможности их правильной реализации. Хотели как лучше, получилось как всегда.
Изучать их нужно для формального прохождения собеседования. Далее, в 90% случаев вы будете писать код с минимальным использованием паттернов. Никто не даст вам проектировать архитектуру бизнес приложения, где ошибка это потерянные миллионы. Но вы можете всегда поиграться, реализовав паттерн в вашем маленьком пет проекте.
Или снять ролик, где расскажете как использовать паттерн, чтобы сказать на собеседовании, что вы не только знаете паттерны, а ещё обучаете других людей.
@@NewUser78654 Полную околесицу несешь. Здесь канал о геймдеве и конкретно юнити. Какие бизнес-приложения, какие потерянные миллионы. Попробуй напиши игру без игрового цикла (тоже, внезапно, паттерн) или управление сложного персонажа без машины состояний. Ты поехавший.
@@user-sx7vo6kg8t паттерны нужны, но к месту. Не надо их тыкать кругом.
Спасибо за урок! У меня практический вопрос к автору канала и опытным разработчикам. Вот если мы применяем компонент Animator к некому персонажу или объекту, то какая практика считается хорошей, использовать машину состояний этого аниматора или дублировать ее своей и синхронизировать со стейтами аниматора?
Чем меньше код привязан к движку, тем лучше. Теоретический перенос механики в другой проект в дальнейшем намного упростится не завися от каких-то компонентов.
да все хорошо, конечно, но как обращаться к скриптам которые на сцене, например если ты бежишь то изменить фокус на камере? Да хоть что так как монобех мы как я понимаю из состояний убераем, то и со сценой ни каких взаимодействий не будет. Например при хотьбе или беге что бы включались звуки шагов. И как проверить какое текущее состояние? Например если идле то отключить звук шелеста плаща?
Так State - Mashine и есть новичковый паттерн. Его сразу после Синглтона изучают.
Как писать fsm понятно, а что с ним дальше делать и как его использовать - не понятно.
Я не понял. Сначала FsmStateWalk наследовался от FsmState, но потом там появились transform и speed, получается, теперь FsmStateWalk наследуется от FsmStateMovement? А как же SetState тогда, где T должно быть FsmState? И вообще, что это за тип данных Type? У меня на него движок ругается, из-за этого ничего не работает.
Type это специальный тип данных для хранения названия типа данных. Например, можно написать так: Type t = typeof(String); Здесь он для того, что бы в список состояний нельзя было добавить два состояния одного типа. При попытке добавить повторно такой ключ уже будет.
Привет! Подскажите, пожалуйста, если я пишу простенький ИИ на основе FSM и мне необходимо, чтобы внутри какого-то состояния прокидывался рейкаст или в целом использовались какие-то монобеховские штуки, будет ли правильно наследовать базовый FsmState от монобеха?
Или лучше сделать метод, который принимает RayCastHit на уровне абстрактного класса FsmState и вызывать его в апдейте класса FsmExample по типу _currentState?.GetRaycast(hit);
@@styleoflazyphotography лучше вызывать метод FixedUpdate на FsmExample, соответственно в абстрактном классе FsmState добавить метод virtual FixedUpdate, и реализовать только в тех состояниях, где это надо
Привет, никак у тебя на канале не могу найти создание каких-то конкретных игр.(Возможно просто не нашёл) Очень хотелось бы посмотреть на применение всех фишек из твоих видосов на деле.
Такие видео начнутся в обозримом будущем, пока их нет)
Базово урок хороший, но мне кажется, что вы не очень явно выделили абстракцию.
У вас у одного класса состояния можно быть только один экземпляр.
Но как нам действовать, если у одного состояния могут быть разные параметры?
Например, состояние стана, которое может длиться разное время время в зависимости от полученного урона.
Может сразу PlayMayker поставить, не?
Если есть деньги, то конечно эффективнее сразу PlayMaker ставить.
Пиратить тоже можно, но от этого могут появляться разного рода проблемы, не рекомендую
понятно, но зачем вообще это использовать?
какие то плюсы для серверной части? лучше при контроле античитом? лучше контроль за игроками в мультиплеере? почему нельзя просто получать или собирать состояния обычной стейтмашин каждого экземляра? зачем этот навес, интересно
Паттерн - это почти модно. Мода на них прошла, лет пять назад (Но это не точно (с)). Паттерн - это фишка на собеседовании, показать а знаешь ли ты GOF, банду четырех, Дядю Боба - модных и распиаренных чуваков из айти. Реального толку от паттерна мало.
Мы планируем, выбираем паттерн, реализуем, работает - модифицируем, изменяем под новые требования бизнеса/заказчика, получаем легаси код. )
Анализируем, выбираем паттерн, переписываем всё с нуля (о да - типовое в вакансиях, мы крутые ты нам нужен чтобы переписать легаси код) - модифицируем...снова легаси. Паттерн? Не сработал.
Кто вообще сказал, что код должен подчиняться паттерну, быть написан по паттерну? Заиграл технический долг в одном месте?
Прихожу к бизнес аналитику - говорю какие у вас паттерны? Смотрит удивленно - у нас тут бизнес, а не игрушки. Вот система, автоматически генерирующая архитектуру под изменяющиеся бизнес задачи - мы "рисуем" логику, она создает архитектуру. А программисты наполняют всё это кодом, без изменения архитектуры - заполнить готовый класс, метод. Никакого создания своего класса, объекта и прочих вещей.
@@NewUser78654 Паттерны это просто общий "язык", способ формализации проблем и решений, которые и так есть в любом коде. Даже когда ты не применяешь паттерны, ты их применяешь, как минимум потому, что в любом современном высокоуровневом языке (типа C# ) или движке (типа Unity) часть из них уже вшита и используется, а часть ты "переизобретаешь" пока пишешь свою программу. В C# вшиты нативные события, коллекции, итераторы и так далее, в Unity из коробки есть те же события, компонент (в любом монобехе), прототип (в перфабах), машина состояний (в аниматоре), апдейт, игровой цикл, а в плагинах и того больше. Ты не можешь написать сколько-нибудь сложную программу и особенно игру без использования паттернов. Банальный пул объектов это тоже паттерн. Просто ты, видимо, не знаешь о том, что та или иная проблема давно уже считается типовой, решается стандартно и у нее есть общее название, которое понимают другие программисты.
@@NewUser78654 По комментам в других постах я уже понял, что ты вообще никакого отношения к C# и Unity не имеешь, а может и геймдеву, только ходишь и теоретизируешь, пуляя глупости невпопад.
@@NewUser78654 паттерн - это не реализация, это общая идея решения задачи, "шаблон". Суть архитектуры не мазюкать грязными ручками тяп-ляпы, а использовать структурный подход, а любой структурный подход по сути является шаблонным, т.е. принадлежит к какому то паттерну
Здравствуй, хочу реализовать реалистичное поведение персонажа, с учетом костей, с учетом физики... Движение ног влево, вправо, вперед, назад... Приятное поведение модели персонажа, лучше IK и анимации создать в блендере, а потом настраивать в юнити? Или лучше в блендере создать риггинг и через код в юнити создать IK, я видел там по поводу этого есть методы... У одного ютубера видел SHIMORO у него написано через IK... Размышляю по этому поводу, надеюсь у кого-то есть соображение, что лучше и как это реализовать. Было приятно если есть статья или видео на ютуб по этому поводу... Заранее спасибо...
Лучше взять готовое хорошо сделанное и разобрать по полочкам, пробовать собрать тоже самое с нуля рядышком. Самому с нуля разбираться очень долго и на это уйдут недели и месяцы труда.
Материалов не подскажу, т.к. не использую такой подход, увы
@@gamedevlavka Хорошо, спасибо... Буду пробовать...
В чем разница между FSM и паттерном Состояние?
Состояние - это идея о том, что у объекта есть состояния и их можно переключать (абстрактная идея). FSM - идея о том, что объект обладает конечным количеством конкретных состояний, заключённых в одну сущность
Контекст в паттерне Состояние - это и есть машина состояний, просто в него добавлена логика хранения всех состояний, чтобы при каждой смене состояния не создавать новое через new. А FSM - это контейнер компонентов, где компоненты как бы состояния, а контейнер как бы машина состояний. FSM не имеет к паттерну Состояние, как и к машине состояний, никакого отношения.
Nu blyat chto proisxodit tam?
Как-то некрасиво передавать ссылку на fsm в конструкторе состояний. Проще сразу делать это внутри метода AddState. Сделать метод SetFsm для класса fsmState или как-то так. Ведь раньше чем состояние добавится нам эта ссылка всё равно нужна не будет. Все методы состояния вызываются только после его добавления через смену состояний.
зачем придумывают на каждую элементарную часть программирования отдельные названия и постоянно используют слова типа "паттерн"? чтобы видео записывать на ютубе и курсы продавать? скоро будут видимо курсы по паттерну нажать энтер или паттерн использования переменных, паттерн написания пробелов...
В целом ты прав, паттерны привносят больше конструктивы, т.е. это именнованные способы решения задач, и в дискуссии достаточно укзать название а не описывать принцип работы.
Все супер, но есть момент. Если перемещение основано на физике (через компонент Rigidbody), то возникает сложность. Поясню, инпут хорошо читается в методе жизненного цикла Update, а всю работу с физикой хорошо делать в методе FixedUpdate. Как тут быть? Есть ли какое-то элегантное решение без добавления костылей в данный паттерн? UPD: для себя решил в FsmState добавить виртуальный метод PhysicsUpdate, тем самым разделив обработку инпута и обновление физики.
Хорошее решение. При этом не забывай, что FSM можно строить разные, одну с физикой, другую без физики. Это как пример тебе с намеком)