Паттерн 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

КОМЕНТАРІ • 62

  • @user-sx7vo6kg8t
    @user-sx7vo6kg8t Рік тому +23

    Урок хороший, но как мне кажется совсем для новичков, а для новичков куча реализаций. Хотелось бы наверное более углубиться в раскрытие темы, т.к. на базе State machine строят архитектуры приложений. Поговорить о вариациях Transitions, возможно зацепить реализации с async, может быть построить какой-нибудь WindowManager. Построение простой архитектуры через StateMachine. Связывание например StateMachine и View. Может быть StateMachine и Zenject рассмотреть. Просто паттерн очень часто используется, а качественных уроков по его применению не особо много, кроме условного состояния персонажа. А так спасибо за видос!

    • @samserious5483
      @samserious5483 Рік тому +1

      Не, Zenject не надо, эту какаху вообще не надо

    • @almightiey0.0
      @almightiey0.0 Рік тому

      @@samserious5483 а какая лучшая альтернатива?

    • @samserious5483
      @samserious5483 Рік тому +2

      @@almightiey0.0 написать то, что лучше всего подходит проекту конуретному

    • @exregisterqq
      @exregisterqq Рік тому +2

      @@samserious5483 zenject используют повсеместно. и неспроста - это лучший di контейнер. единственный минус заключается в его массивности и, наверное, в сложности освоения. для масштабных проектов - идеальный фреймворк. однако, для небольших лучше взять просто сервис локатор и не парится

  • @user-qy9zz7fk1l
    @user-qy9zz7fk1l Рік тому +2

    Отличный урок. Хотелось бы еще одним щелчком скачать данный пример.
    Спасибо за урок!

  • @olexkov4643
    @olexkov4643 3 місяці тому +2

    Наверное лучший канал по юньке который я видел...

  • @aleksey8405
    @aleksey8405 Рік тому +2

    Спасибо за полезный контент.

  • @exregisterqq
    @exregisterqq Рік тому +8

    неплохо вышло, но не могу не заметить пару замечаний
    1) метод AddState лучше сделать генерик, как и SetState, тогда не придется вызывать метод GetType, который выполняется в рантайме, а заменить на typeof(T), выполняющийся на этапе компиляции
    2) можно кэшировать Type (который также будет браться через typeof) последнего установленного стейта и в проверке на одинаковый тип тоже можно убрать GetType, а оставить что то типа:
    if (currentStateType == typeof(T)) return
    жду новых видосов)

    • @exregisterqq
      @exregisterqq Рік тому +2

      вообще у меня на гите лежит еще более сложная стейт машина, мог бы дать тебе на ревью)

    • @gamedevlavka
      @gamedevlavka  Рік тому +2

      Со всем согласен) мне главное смысл показать)
      А реализаций, как я и сказал, чуть ли не бесконечность)
      На гите давай, с радостью гляну)

    • @exregisterqq
      @exregisterqq Рік тому

      @@gamedevlavka скину в телегу, здесь удаляет

  • @vladimirkalugin-devstudio9721
    @vladimirkalugin-devstudio9721 Рік тому +1

    Круто спасибо!

  • @sodden_steam
    @sodden_steam Рік тому +2

    Отличное видео. Кто хочет понять Стэйт Машину- Вам сюда. Автор всё отлично объяснил.

  • @forcesoftheevil9252
    @forcesoftheevil9252 Рік тому +1

    Хорошее видео. Не посмотрел раньше из-за сессии + сейчас в проекте я бомбанул и переписываю машину состоянии))0)
    Ещё приятно слышать твой радостный голос в видео))

    • @gamedevlavka
      @gamedevlavka  Рік тому

      Радостный? А обычно какой?)

    • @forcesoftheevil9252
      @forcesoftheevil9252 Рік тому

      @@gamedevlavka Я помню как серьёзный и вдумчивый. Значит из-за универа забыл :Р

  • @aarontower
    @aarontower Рік тому +2

    Даа) Область применения фсм у меня страдает) жаль что без транзишн с ней у меня как раз проблемы)

  • @skitalex49rus
    @skitalex49rus Рік тому +3

    Ещё бы урок по zenject

  • @dmitriypermyakov5402
    @dmitriypermyakov5402 Рік тому +4

    Ничего не понял, но очень интересно.

    • @NewUser78654
      @NewUser78654 Рік тому

      А ничего и не надо понимать. Напридумывали всякой ерунды (паттернов), мало было GOF - так вот получите 100+ паттернов. И реализуют эту выдумку разными способами. И паттерны и гибкая методология и фреймворки - легаси код на выходе ) А есть ещё и антипаттерны...
      Паттерн должен был решать типовую задачу, но когда их стало более ста, когда у каждого стало несколько реализаций, когда базовый mvc трактуют как тонкий-толстый контроллер и устраивают холивары (и еще какие и на любых уровнях от джуна до синьора)...есть над чем подумать.

    • @user-sx7vo6kg8t
      @user-sx7vo6kg8t Рік тому +3

      А в чем твой пункт? Паттерны не нужны? Или их не нужно изучать? Поясни мысль.

    • @NewUser78654
      @NewUser78654 Рік тому

      @@user-sx7vo6kg8t паттерны не работают и не решают задачи бизнеса. Да, по сути они не нужны в силу невозможности их правильной реализации. Хотели как лучше, получилось как всегда.
      Изучать их нужно для формального прохождения собеседования. Далее, в 90% случаев вы будете писать код с минимальным использованием паттернов. Никто не даст вам проектировать архитектуру бизнес приложения, где ошибка это потерянные миллионы. Но вы можете всегда поиграться, реализовав паттерн в вашем маленьком пет проекте.
      Или снять ролик, где расскажете как использовать паттерн, чтобы сказать на собеседовании, что вы не только знаете паттерны, а ещё обучаете других людей.

    • @user-qb8lx2uq5j
      @user-qb8lx2uq5j Рік тому +4

      @@NewUser78654 Полную околесицу несешь. Здесь канал о геймдеве и конкретно юнити. Какие бизнес-приложения, какие потерянные миллионы. Попробуй напиши игру без игрового цикла (тоже, внезапно, паттерн) или управление сложного персонажа без машины состояний. Ты поехавший.

    • @dmitriypermyakov5402
      @dmitriypermyakov5402 Рік тому +1

      @@user-sx7vo6kg8t паттерны нужны, но к месту. Не надо их тыкать кругом.

  • @user-qb8lx2uq5j
    @user-qb8lx2uq5j Рік тому +2

    Спасибо за урок! У меня практический вопрос к автору канала и опытным разработчикам. Вот если мы применяем компонент Animator к некому персонажу или объекту, то какая практика считается хорошей, использовать машину состояний этого аниматора или дублировать ее своей и синхронизировать со стейтами аниматора?

    • @user-sx7vo6kg8t
      @user-sx7vo6kg8t Рік тому +6

      Чем меньше код привязан к движку, тем лучше. Теоретический перенос механики в другой проект в дальнейшем намного упростится не завися от каких-то компонентов.

  • @user-mh2ll7cg7x
    @user-mh2ll7cg7x 2 місяці тому

    да все хорошо, конечно, но как обращаться к скриптам которые на сцене, например если ты бежишь то изменить фокус на камере? Да хоть что так как монобех мы как я понимаю из состояний убераем, то и со сценой ни каких взаимодействий не будет. Например при хотьбе или беге что бы включались звуки шагов. И как проверить какое текущее состояние? Например если идле то отключить звук шелеста плаща?

  • @nightkot4917
    @nightkot4917 8 місяців тому

    Так State - Mashine и есть новичковый паттерн. Его сразу после Синглтона изучают.

  • @Kostarasta
    @Kostarasta 3 дні тому

    Как писать fsm понятно, а что с ним дальше делать и как его использовать - не понятно.

  • @user-tm5ie2wx1x
    @user-tm5ie2wx1x 8 місяців тому +1

    Я не понял. Сначала FsmStateWalk наследовался от FsmState, но потом там появились transform и speed, получается, теперь FsmStateWalk наследуется от FsmStateMovement? А как же SetState тогда, где T должно быть FsmState? И вообще, что это за тип данных Type? У меня на него движок ругается, из-за этого ничего не работает.

    • @iceDregonFox
      @iceDregonFox 3 місяці тому

      Type это специальный тип данных для хранения названия типа данных. Например, можно написать так: Type t = typeof(String); Здесь он для того, что бы в список состояний нельзя было добавить два состояния одного типа. При попытке добавить повторно такой ключ уже будет.

  • @styleoflazyphotography
    @styleoflazyphotography 3 місяці тому

    Привет! Подскажите, пожалуйста, если я пишу простенький ИИ на основе FSM и мне необходимо, чтобы внутри какого-то состояния прокидывался рейкаст или в целом использовались какие-то монобеховские штуки, будет ли правильно наследовать базовый FsmState от монобеха?

    • @styleoflazyphotography
      @styleoflazyphotography 3 місяці тому

      Или лучше сделать метод, который принимает RayCastHit на уровне абстрактного класса FsmState и вызывать его в апдейте класса FsmExample по типу _currentState?.GetRaycast(hit);

    • @artemyzotov
      @artemyzotov 3 місяці тому

      ​@@styleoflazyphotography лучше вызывать метод FixedUpdate на FsmExample, соответственно в абстрактном классе FsmState добавить метод virtual FixedUpdate, и реализовать только в тех состояниях, где это надо

  • @Ketchuppp115
    @Ketchuppp115 Рік тому +1

    Привет, никак у тебя на канале не могу найти создание каких-то конкретных игр.(Возможно просто не нашёл) Очень хотелось бы посмотреть на применение всех фишек из твоих видосов на деле.

    • @gamedevlavka
      @gamedevlavka  Рік тому

      Такие видео начнутся в обозримом будущем, пока их нет)

  • @user-my1is1ei2j
    @user-my1is1ei2j Рік тому

    Базово урок хороший, но мне кажется, что вы не очень явно выделили абстракцию.
    У вас у одного класса состояния можно быть только один экземпляр.
    Но как нам действовать, если у одного состояния могут быть разные параметры?
    Например, состояние стана, которое может длиться разное время время в зависимости от полученного урона.

  • @_fes_1350
    @_fes_1350 Рік тому +2

    Может сразу PlayMayker поставить, не?

    • @gamedevlavka
      @gamedevlavka  Рік тому

      Если есть деньги, то конечно эффективнее сразу PlayMaker ставить.
      Пиратить тоже можно, но от этого могут появляться разного рода проблемы, не рекомендую

  • @KENISEG
    @KENISEG Рік тому +3

    понятно, но зачем вообще это использовать?
    какие то плюсы для серверной части? лучше при контроле античитом? лучше контроль за игроками в мультиплеере? почему нельзя просто получать или собирать состояния обычной стейтмашин каждого экземляра? зачем этот навес, интересно

    • @NewUser78654
      @NewUser78654 Рік тому

      Паттерн - это почти модно. Мода на них прошла, лет пять назад (Но это не точно (с)). Паттерн - это фишка на собеседовании, показать а знаешь ли ты GOF, банду четырех, Дядю Боба - модных и распиаренных чуваков из айти. Реального толку от паттерна мало.
      Мы планируем, выбираем паттерн, реализуем, работает - модифицируем, изменяем под новые требования бизнеса/заказчика, получаем легаси код. )
      Анализируем, выбираем паттерн, переписываем всё с нуля (о да - типовое в вакансиях, мы крутые ты нам нужен чтобы переписать легаси код) - модифицируем...снова легаси. Паттерн? Не сработал.
      Кто вообще сказал, что код должен подчиняться паттерну, быть написан по паттерну? Заиграл технический долг в одном месте?
      Прихожу к бизнес аналитику - говорю какие у вас паттерны? Смотрит удивленно - у нас тут бизнес, а не игрушки. Вот система, автоматически генерирующая архитектуру под изменяющиеся бизнес задачи - мы "рисуем" логику, она создает архитектуру. А программисты наполняют всё это кодом, без изменения архитектуры - заполнить готовый класс, метод. Никакого создания своего класса, объекта и прочих вещей.

    • @user-qb8lx2uq5j
      @user-qb8lx2uq5j Рік тому +3

      @@NewUser78654 Паттерны это просто общий "язык", способ формализации проблем и решений, которые и так есть в любом коде. Даже когда ты не применяешь паттерны, ты их применяешь, как минимум потому, что в любом современном высокоуровневом языке (типа C# ) или движке (типа Unity) часть из них уже вшита и используется, а часть ты "переизобретаешь" пока пишешь свою программу. В C# вшиты нативные события, коллекции, итераторы и так далее, в Unity из коробки есть те же события, компонент (в любом монобехе), прототип (в перфабах), машина состояний (в аниматоре), апдейт, игровой цикл, а в плагинах и того больше. Ты не можешь написать сколько-нибудь сложную программу и особенно игру без использования паттернов. Банальный пул объектов это тоже паттерн. Просто ты, видимо, не знаешь о том, что та или иная проблема давно уже считается типовой, решается стандартно и у нее есть общее название, которое понимают другие программисты.

    • @user-qb8lx2uq5j
      @user-qb8lx2uq5j Рік тому +1

      @@NewUser78654 По комментам в других постах я уже понял, что ты вообще никакого отношения к C# и Unity не имеешь, а может и геймдеву, только ходишь и теоретизируешь, пуляя глупости невпопад.

    • @nightyonetwothree
      @nightyonetwothree Рік тому +2

      @@NewUser78654 паттерн - это не реализация, это общая идея решения задачи, "шаблон". Суть архитектуры не мазюкать грязными ручками тяп-ляпы, а использовать структурный подход, а любой структурный подход по сути является шаблонным, т.е. принадлежит к какому то паттерну

  • @jonathansantos6026
    @jonathansantos6026 Рік тому +2

    Здравствуй, хочу реализовать реалистичное поведение персонажа, с учетом костей, с учетом физики... Движение ног влево, вправо, вперед, назад... Приятное поведение модели персонажа, лучше IK и анимации создать в блендере, а потом настраивать в юнити? Или лучше в блендере создать риггинг и через код в юнити создать IK, я видел там по поводу этого есть методы... У одного ютубера видел SHIMORO у него написано через IK... Размышляю по этому поводу, надеюсь у кого-то есть соображение, что лучше и как это реализовать. Было приятно если есть статья или видео на ютуб по этому поводу... Заранее спасибо...

    • @gamedevlavka
      @gamedevlavka  Рік тому +1

      Лучше взять готовое хорошо сделанное и разобрать по полочкам, пробовать собрать тоже самое с нуля рядышком. Самому с нуля разбираться очень долго и на это уйдут недели и месяцы труда.
      Материалов не подскажу, т.к. не использую такой подход, увы

    • @jonathansantos6026
      @jonathansantos6026 Рік тому +2

      @@gamedevlavka Хорошо, спасибо... Буду пробовать...

  • @xagent
    @xagent Рік тому

    В чем разница между FSM и паттерном Состояние?

    • @gamedevlavka
      @gamedevlavka  Рік тому +2

      Состояние - это идея о том, что у объекта есть состояния и их можно переключать (абстрактная идея). FSM - идея о том, что объект обладает конечным количеством конкретных состояний, заключённых в одну сущность

    • @user-sc8dc8cf8e
      @user-sc8dc8cf8e 4 місяці тому

      Контекст в паттерне Состояние - это и есть машина состояний, просто в него добавлена логика хранения всех состояний, чтобы при каждой смене состояния не создавать новое через new. А FSM - это контейнер компонентов, где компоненты как бы состояния, а контейнер как бы машина состояний. FSM не имеет к паттерну Состояние, как и к машине состояний, никакого отношения.

  • @MDarksider
    @MDarksider Місяць тому +1

    Nu blyat chto proisxodit tam?

  • @mrgoodpeople
    @mrgoodpeople 4 місяці тому

    Как-то некрасиво передавать ссылку на fsm в конструкторе состояний. Проще сразу делать это внутри метода AddState. Сделать метод SetFsm для класса fsmState или как-то так. Ведь раньше чем состояние добавится нам эта ссылка всё равно нужна не будет. Все методы состояния вызываются только после его добавления через смену состояний.

  • @duoduoo6732
    @duoduoo6732 Рік тому

    зачем придумывают на каждую элементарную часть программирования отдельные названия и постоянно используют слова типа "паттерн"? чтобы видео записывать на ютубе и курсы продавать? скоро будут видимо курсы по паттерну нажать энтер или паттерн использования переменных, паттерн написания пробелов...

    • @SeempleIQ
      @SeempleIQ Рік тому +1

      В целом ты прав, паттерны привносят больше конструктивы, т.е. это именнованные способы решения задач, и в дискуссии достаточно укзать название а не описывать принцип работы.

  • @Baannia
    @Baannia Рік тому +1

    Все супер, но есть момент. Если перемещение основано на физике (через компонент Rigidbody), то возникает сложность. Поясню, инпут хорошо читается в методе жизненного цикла Update, а всю работу с физикой хорошо делать в методе FixedUpdate. Как тут быть? Есть ли какое-то элегантное решение без добавления костылей в данный паттерн? UPD: для себя решил в FsmState добавить виртуальный метод PhysicsUpdate, тем самым разделив обработку инпута и обновление физики.

    • @gamedevlavka
      @gamedevlavka  Рік тому +1

      Хорошее решение. При этом не забывай, что FSM можно строить разные, одну с физикой, другую без физики. Это как пример тебе с намеком)