Первым этапом разработки моей игры стала разработка RTS-движка. Я планирую написать серию постов о возникших задачах и их решениях в этом блоге. В этом посте я расскажу как организовал поведения юнитов.
Размышляя с чего начать вообще этот RTS движок, я пришел к выводу, что стоит начать с конкретики и от нее перейти к абстракции. Первой прикладной задачей, пришедшей на ум, был сбор ресурсов, а точнее, добыча дерева.
Обычно этот процесс в большинстве стратегий заключается в том, что работник при получении указа рубить дерево отправляется к дереву, некоторое время машет возле него киркой топором, затем отправляется к складу и начинает заново.
То есть процесс выглядит примерно так:
Чтоб этот рисунок по настоящему мог претендовать на имя автомата, ему не хватает условий переходов между состояниями и начального и конечного состояния.
Тут все просто: автомат инициализируется с состоянием «Иду рубить», а конец работы происходит во время сдачи. Переходы между состояниями мы можем выразить с помощью следующих условий: «дошел до дерева», «нарубил полную охапку дров», «дошел до склада», «сдал ресурсы». При положительном ответе автомат переходит в следующее состояние, при отрицательном — остается в текущем состоянии.
В каждом из состояний автомата вызывается соответствующее действие при итерации. Так же набор действий может производиться и при переходе между состояниями.
Например, при итерации в состоянии «Сдаю», ресурсы из рюкзака юнита переместятся в склад ресурсов игрока, а при переходе из состояния «Иду рубить» в состояние «Рублю», запустится соответствующая анимация.
Еще отмечу, что сама ходьба не является «атомарной» операцией, встречается во многих поведениях и сама является поведением и по этому на самом деле поведение добычи дерева использует внутри себя поведение ходьбы. То есть новый автомат может быть получен с помощью композиции нескольких других конечных автоматов.
Написав поведения подобным образом, мы получаем архитектурную границу между деталями реализации поведений и высокоуровневой политикой управления этими поведениями. Реализации поведений становятся по сути плагинами ко всей остальной игре, то есть изменения в них не повлияют на корректность работы высокоуровневой логики.
Работают эти поведения посредствам вызова метода iteration из события Update объектов типа Unit (это событие срабатывает каждый кадр). Для связи с остальным миром поведения вызывают методы IStateMachineListener‘a.
Это пример работы конечного автомата строительства в моей игре. Юнит при получении команды строительства отправляется к укзанной точке, а затем переходит в состояние непосредственного конструирования, передавая единицы постройки зданию. Когда здание накопило достаточно единиц постройки, автомат строительства оканчивается и юнит получает новое поведение, поведение по умолчанию.
На этом всё. Если вам нравится или не нравится такой формат, то пишите об этом в комментариях!
Размышляя с чего начать вообще этот RTS движок, я пришел к выводу, что стоит начать с конкретики и от нее перейти к абстракции. Первой прикладной задачей, пришедшей на ум, был сбор ресурсов, а точнее, добыча дерева.
Обычно этот процесс в большинстве стратегий заключается в том, что работник при получении указа рубить дерево отправляется к дереву, некоторое время машет возле него киркой топором, затем отправляется к складу и начинает заново.
То есть процесс выглядит примерно так:
Чтоб этот рисунок по настоящему мог претендовать на имя автомата, ему не хватает условий переходов между состояниями и начального и конечного состояния.
Тут все просто: автомат инициализируется с состоянием «Иду рубить», а конец работы происходит во время сдачи. Переходы между состояниями мы можем выразить с помощью следующих условий: «дошел до дерева», «нарубил полную охапку дров», «дошел до склада», «сдал ресурсы». При положительном ответе автомат переходит в следующее состояние, при отрицательном — остается в текущем состоянии.
В каждом из состояний автомата вызывается соответствующее действие при итерации. Так же набор действий может производиться и при переходе между состояниями.
Например, при итерации в состоянии «Сдаю», ресурсы из рюкзака юнита переместятся в склад ресурсов игрока, а при переходе из состояния «Иду рубить» в состояние «Рублю», запустится соответствующая анимация.
Еще отмечу, что сама ходьба не является «атомарной» операцией, встречается во многих поведениях и сама является поведением и по этому на самом деле поведение добычи дерева использует внутри себя поведение ходьбы. То есть новый автомат может быть получен с помощью композиции нескольких других конечных автоматов.
Написав поведения подобным образом, мы получаем архитектурную границу между деталями реализации поведений и высокоуровневой политикой управления этими поведениями. Реализации поведений становятся по сути плагинами ко всей остальной игре, то есть изменения в них не повлияют на корректность работы высокоуровневой логики.
Работают эти поведения посредствам вызова метода iteration из события Update объектов типа Unit (это событие срабатывает каждый кадр). Для связи с остальным миром поведения вызывают методы IStateMachineListener‘a.
Это пример работы конечного автомата строительства в моей игре. Юнит при получении команды строительства отправляется к укзанной точке, а затем переходит в состояние непосредственного конструирования, передавая единицы постройки зданию. Когда здание накопило достаточно единиц постройки, автомат строительства оканчивается и юнит получает новое поведение, поведение по умолчанию.
На этом всё. Если вам нравится или не нравится такой формат, то пишите об этом в комментариях!
Комментарии (6)
LeVoleur
03.06.2019 09:42Формат не плохой, описание хорошее, детальное, ещё и с иллюстрациями. Для новичков в геймдеве самое то. Но если будет хватать сил, то лучше длиннее статьи делать. Только начал погружаться в неё и она резко закончилась. Ещё было бы хорошо добавить сюда сам код реализации.
Brightori
Один вопрос — зачем? Поведение перемещения это отдельный функционал, рубка леса отдельный функционал, зачем тут
Как мне видится — правильнее в поведении рубки, определять что мы закончили рубить по разным причинам, и запускать следующее поведение.
SanQri Автор
Каким образом мы понимаем какое поведение следующее, если нет родительского автомата? Вариант, в котором поведения цикла добычи дерева добавляют в очередь выполнения свое следующее поведение, мне кажется сложнее, поскольку надо будет хорошо следить за очередью выполнения, так как там могут оказаться кусочки разных поведений.
Это безусловно так. Они и остаются отдельными сущностями, но родительский автомат это сущность, которая определяет переходы между дочерними поведениями.
С помощью иерархического подхода, я описываю ИИ некоторых ботов. То есть даю им поведение, которое никогда не меняется. Изменяемость поведения же полезна для юнитов, контролируемых игроком.