Первым этапом разработки моей игры стала разработка RTS-движка. Я планирую написать серию постов о возникших задачах и их решениях в этом блоге. В этом посте я расскажу как организовал поведения юнитов.

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

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

То есть процесс выглядит примерно так:

image

Чтоб этот рисунок по настоящему мог претендовать на имя автомата, ему не хватает условий переходов между состояниями и начального и конечного состояния.

Тут все просто: автомат инициализируется с состоянием «Иду рубить», а конец работы происходит во время сдачи. Переходы между состояниями мы можем выразить с помощью следующих условий: «дошел до дерева», «нарубил полную охапку дров», «дошел до склада», «сдал ресурсы». При положительном ответе автомат переходит в следующее состояние, при отрицательном — остается в текущем состоянии.

image

В каждом из состояний автомата вызывается соответствующее действие при итерации. Так же набор действий может производиться и при переходе между состояниями.

Например, при итерации в состоянии «Сдаю», ресурсы из рюкзака юнита переместятся в склад ресурсов игрока, а при переходе из состояния «Иду рубить» в состояние «Рублю», запустится соответствующая анимация.

Еще отмечу, что сама ходьба не является «атомарной» операцией, встречается во многих поведениях и сама является поведением и по этому на самом деле поведение добычи дерева использует внутри себя поведение ходьбы. То есть новый автомат может быть получен с помощью композиции нескольких других конечных автоматов.

image

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

Работают эти поведения посредствам вызова метода iteration из события Update объектов типа Unit (это событие срабатывает каждый кадр). Для связи с остальным миром поведения вызывают методы IStateMachineListener‘a.

Это пример работы конечного автомата строительства в моей игре. Юнит при получении команды строительства отправляется к укзанной точке, а затем переходит в состояние непосредственного конструирования, передавая единицы постройки зданию. Когда здание накопило достаточно единиц постройки, автомат строительства оканчивается и юнит получает новое поведение, поведение по умолчанию.


На этом всё. Если вам нравится или не нравится такой формат, то пишите об этом в комментариях!

Комментарии (6)


  1. Brightori
    02.06.2019 04:00

    на самом деле поведение добычи дерева использует внутри себя поведение ходьбы.


    Один вопрос — зачем? Поведение перемещения это отдельный функционал, рубка леса отдельный функционал, зачем тут

    То есть новый автомат может быть получен с помощью композиции нескольких других конечных автоматов.


    Как мне видится — правильнее в поведении рубки, определять что мы закончили рубить по разным причинам, и запускать следующее поведение.


    1. SanQri Автор
      02.06.2019 09:32

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

      Поведение перемещения это отдельный функционал, рубка леса отдельный функционал


      Это безусловно так. Они и остаются отдельными сущностями, но родительский автомат это сущность, которая определяет переходы между дочерними поведениями.

      С помощью иерархического подхода, я описываю ИИ некоторых ботов. То есть даю им поведение, которое никогда не меняется. Изменяемость поведения же полезна для юнитов, контролируемых игроком.


  1. plus
    02.06.2019 07:49

    Вы изобрели state (GOF). Или я ошибаюсь?


    1. neochief
      02.06.2019 09:22

      State — это конечный автомат на объектах. Автомат может быть реализован и не на объектах.


    1. SanQri Автор
      02.06.2019 09:36

      Вы правы. Только шаблон состояние модифицирован еще и компоновщиком.


  1. LeVoleur
    03.06.2019 09:42

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